shardingsphere5.x整合springboot分库分表实战

news2024/11/26 0:45:59

官方文档不同版本配置变更记录:Spring Boot Start 配置 :: ShardingSphere

pom.xml配置:

<!--shardingsphere分库分表依赖-->
<dependency>
	<groupId>org.apache.shardingsphere</groupId>
	<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
	<version>5.1.1</version>
</dependency>

<!--mybatis-plus依赖-->
<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>3.4.0</version>
</dependency>

建表sql:

CREATE TABLE `orders_0` (
  `id` bigint NOT NULL COMMENT '主键',
  `order_no` varchar(255) NOT NULL COMMENT '订单号',
  `user_id` bigint NOT NULL COMMENT '用户id',
  `pay_amount` decimal(20,2) NOT NULL DEFAULT '0' COMMENT '支付金额',
  `order_status` int NOT NULL COMMENT '订单状态 1-已预约 2-已取车 3-已还车 4-已取消',
  `pay_status` int NOT NULL DEFAULT '0' COMMENT '支付状态 0-未支付 1-支付成功',
  `pay_method` int DEFAULT NULL COMMENT '支付方式 1-微信 2-支付宝',
  `pay_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;


CREATE TABLE `orders_1` (
  `id` bigint NOT NULL COMMENT '主键',
  `order_no` varchar(255) NOT NULL COMMENT '订单号',
  `user_id` bigint NOT NULL COMMENT '用户id',
  `pay_amount` decimal(20,2) NOT NULL DEFAULT '0' COMMENT '支付金额',
  `order_status` int NOT NULL COMMENT '订单状态 1-已预约 2-已取车 3-已还车 4-已取消',
  `pay_status` int NOT NULL DEFAULT '0' COMMENT '支付状态 0-未支付 1-支付成功',
  `pay_method` int DEFAULT NULL COMMENT '支付方式 1-微信 2-支付宝',
  `pay_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

......

CREATE TABLE `orders_9` (
  `id` bigint NOT NULL COMMENT '主键',
  `order_no` varchar(255) NOT NULL COMMENT '订单号',
  `user_id` bigint NOT NULL COMMENT '用户id',
  `pay_amount` decimal(20,2) NOT NULL DEFAULT '0' COMMENT '支付金额',
  `order_status` int NOT NULL COMMENT '订单状态 1-已预约 2-已取车 3-已还车 4-已取消',
  `pay_status` int NOT NULL DEFAULT '0' COMMENT '支付状态 0-未支付 1-支付成功',
  `pay_method` int DEFAULT NULL COMMENT '支付方式 1-微信 2-支付宝',
  `pay_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

yml配置:

spring:
  shardingsphere:
    datasource:
      common:
        driver-class-name: com.mysql.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
      names: db0,db1
      db0:
        url: jdbc:mysql://localhost:3306/test
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
      db1:
        url: jdbc:mysql://localhost:3306/zkq_oms_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
    # 默认数据源,未分片的表默认执行库
    sharding:
        default-data-source-name: db1
    rules:
     sharding:
        key-generators:
          # 此处必须要配置,否则会导致报错,因为shardingsphere-jdbc-core-spring-boot-starter需要加载此项配置,官网的demo例子有错
          # 分布式序列算法:https://shardingsphere.apache.org/document/current/cn/user-manual/common-config/builtin-algorithm/keygen/
          snowflake:
            type: SNOWFLAKE
            props:
              # 在单机模式下支持用户自定义配置,如果用户不配置使用默认值为0。
              # 在集群模式下会由系统自动生成,相同的命名空间下不会生成重复的值。
              worker-id: 0
        sharding-algorithms:
          # 分片算法:https://shardingsphere.apache.org/document/current/cn/user-manual/common-config/builtin-algorithm/sharding/
          table-mod:
            # 取模类型分片键的值必须是数字,否则会报错
            type: MOD
            props:
              sharding-count: 10
        tables:
          orders:
            # 配置逻辑表:orders与真实库表的对应规则
            actual-data-nodes: db0.orders_$->{0..9}
            # 配置分表规则
            table-strategy:
              standard:
                sharding-column: order_no
                sharding-algorithm-name: table-mod
    enabled: true
    # 展示修改以后的sql语句
    props:
      sql-show: true


mybatis:
    configuration:
        map-underscore-to-camel-case: true
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    type-aliases-package: com.example.demo.entity
    mapper-locations: classpath:mapper/*.xml

orders对象实体:

package com.example.demo.entity;


import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

@Data
public class Orders implements Serializable {
    
    @TableId
    private Long id;

    /**
     * 订单号
     */
    private String orderNo;

    /**
     * 用户id
     */
    private Long userId;

    /**
     * 订单状态 1-已预约 2-已取车 3-已还车 4-已取消
     */
    private Integer orderStatus;

    /**
     * 支付状态 0-未支付 1-支付成功
     */
    private Integer payStatus;

    /**
     * 支付方式 1-微信 2-支付宝
     */
    private Integer payMethod;

    /**
     * 支付金额
     */
    private BigDecimal payAmount;

    /**
     * 支付时间
     */
    private Date payTime;

    /**
     * 创建时间
     */
    private Date createdAt;

    /**
     * 修改时间
     */
    private Date updatedAt;
}

OrdersMapper: 

package com.example.demo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;

import com.example.demo.entity.Orders;

import java.util.List;

@Repository
public interface OrdersMapper extends BaseMapper<Orders> {
	
	Orders getOrderByNo(String orderNo);

	List<Orders> getOrderList();
}

OrdersMapper.xml: 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
	namespace="com.example.demo.mapper.OrdersMapper">

	<sql id="Base_Column_List">
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	</sql>


	<select id="getOrderByNo" parameterType="java.lang.String"
		resultType="com.example.demo.entity.Orders">
		select
		<include refid="Base_Column_List" />
		from orders where order_no=#{orderNo}
	</select>

	<select id="getOrderList" resultType="com.example.demo.entity.Orders">
		select
		<include refid="Base_Column_List" />
		from orders order by created_at desc limit 10, 10
	</select>
</mapper>

单元测试: 

package com.example.demo;

import com.example.demo.mapper.OrdersMapper;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.example.demo.entity.Orders;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTest {

	@Autowired
	private OrdersMapper ordersMapper;

    @Test
	public void saveOrder() {
		Orders orders = new Orders();
		orders.setOrderNo("297454965260130002");
		orders.setUserId(2L);
		orders.setPayAmount(new BigDecimal("32"));
		orders.setOrderStatus(1);
		orders.setPayStatus(1);
		orders.setPayMethod(1);
		orders.setPayTime(new Date());
		orders.setCreatedAt(new Date());
		orders.setUpdatedAt(new Date());
		ordersMapper.insert(orders);
	}

	@Test
	public void contextLoads() {
		Orders order = ordersMapper.getOrderByNo("297454965260130002");
		System.out.println("查询结果:" + order);
	}

	@Test
	public void getOrderList() {
        List<Orders> orderList = ordersMapper.getOrderList();
        orderList.forEach((e)-> System.out.println("查询结果:" + e));
	}
}

1、插入数据结果,按order_no分片取模,分片数为10,该数据被写入表orders_2:

2、查询数据sql,按order_no分片取模,分片数为10,该数据直接查询表orders_2:

 3、未传分片键,执行ordersMapper.getOrderList(); 查询所有表:

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2fcad739] was not registered for synchronization because synchronization is not active
JDBC Connection [org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection@4e93d23e] will not be managed by Spring
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Logic SQL: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders order by created_at desc limit 10, 10 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional[org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment@6c65c6f0], lock=Optional.empty, window=Optional.empty) 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_0 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_1 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_2 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_3 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_4 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_5 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_6 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_7 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,294 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_8 order by created_at desc limit 0, 20 
[INFO ] 2022-12-26 16:38:50,295 --main-- [ShardingSphere-SQL] Actual SQL: db0 ::: select
		 
		order_no, user_id, pay_amount, order_status, pay_status, pay_method,
		pay_time, created_at, updated_at
	 
		from orders_9 order by created_at desc limit 0, 20 
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2fcad739]

根据以上日志可以看到,逻辑sql为:

select order_no, user_id, pay_amount, order_status, pay_status, pay_method, pay_time, created_at, updated_at  from orders order by created_at desc limit 10, 10;

但实际sql是分别查询orders_0到orders_9,limit 0, 20

这是由于shardingsphere会对逻辑sql进行路由、改写,然后归并结果集。所以在使用中一定要注意,未传分片键查询的话会造成广播路由(用于处理对数据库中与其逻辑表相关的所有真实表的操作,主要包括不带分片键的DQL和DML,以及DDL等)

注:shardingsphere-jdbc在采用主从模型时,为了保证主从库间的事务一致性,避免跨服务的分布式事务,添加@Transactional事务注解开启事务后,事务中的数据读写均用主库。(在JUnit环境下的@Transactional注解,默认情况下会对事务进行回滚)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/621675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式锁原理与实战一:分布式锁简介

跨JVM的线程安全问题 在单体的应用开发场景中&#xff0c;在多线程的环境下&#xff0c;涉及并发同步的时候&#xff0c;为了保证一个代码块在同一时间 只能由一个线程访问&#xff0c;我们一般可以使用 synchronized 语法和 ReetrantLock 去保证&#xff0c;这实际上是本地锁…

指针--间接寻址运算符

通常&#xff0c;只要指明要访问的变量的内存地址&#xff0c;即可直接访问变量所在的存储单元中的内容。在前面都是直接通过变量名来访问变量的内容。直接按变量名或者变量的地址存取变量的内容的访问方式&#xff0c; 称为 直接寻址&#xff08;Direct Addressing&#xff09…

STM32读取BH1750光照强度数据打印到串口

【1】BH1750是什么&#xff1f; BH1750是一种数字式环境光强度传感器&#xff08;Digital Light Sensor&#xff09;&#xff0c;也称为其他名称&#xff0c;例如GY-302传感器、BH1750FVI传感器等。它的工作原理是通过收集光线照射到传感器上的量来测量环境亮度。 使用I2C&am…

操作系统 第三章 3.2 错题整理

页面引用串长度是什么意思 合法位存在位 不存在即发生故障 区分好页表项和逻辑地址 是不同的 逻辑地址48bit 偏移量12bit 页号36bit 页表项8B 4KB/8B2^9 一个页面能存放2^9个页表项 页号9bit&#xff0c;36/94 虚拟存储器包括内存和磁盘对换区&#xff0c;工作集要频繁用到&…

深度学习:使用UNet做图像语义分割,训练自己制作的数据集,详细教程

语义分割(Semantic Segmentation)是图像处理和机器视觉一个重要分支。与分类任务不同&#xff0c;语义分割需要判断图像每个像素点的类别&#xff0c;进行精确分割。语义分割目前在自动驾驶、自动抠图、医疗影像等领域有着比较广泛的应用。我总结了使用UNet网络做图像语义分割的…

我们不一样-康耐视visionpro和apple vision pro

​ 机器视觉Halcon-不同颜色快速识别 康耐视Visionpro是美国cognex visionpro。 康耐视 VisionPro 是领先的计算机式视觉软件。它主要用于设置和部署视觉应用 - 无论是使用相机还是图像采集卡。借助 VisionPro,用户可执行各种功能,包括几何对象定位和检测、识别、测量和对准…

【Web服务应用】LVS负载均衡集群

LVS负载均衡集群 一、企业级集群含义1.1集群的含义1.2LVS一些专业术语 二、企业集群分类2.1负载均衡集群2.2高可用集群2.3高性能运算集群&#xff08;High Performance Computer Cluster&#xff09; 三、负载均衡的架构3.1负载均衡的结构 四、负载均很集群的工作模式4.1NAT模式…

JDBC连接数据库步骤(入门到进阶全)

目录 一、JDBC是什么&#xff1f; 二&#xff0c;JDBC的本质是什么&#xff1f; 为什么要用面向接口编程&#xff1f; 三、JDBC实现原理 四、使用idea开发JDBC代码配置驱动 ​编辑 五、JDBC编程六步概述 六、JDBC编程实现 1.插入实现 2.删除与更新实现 3 .类加载的方式注…

Jetson AGX Orin安装Anaconda、Cuda、Cudnn、Pytorch、Tensorrt最全教程

文章目录 一&#xff1a;Anaconda安装二&#xff1a;Cuda、Cudnn安装三&#xff1a;Pytorch安装四&#xff1a;Tensorrt安装 一&#xff1a;Anaconda安装 Jetson系列边缘开发板&#xff0c;其架构都是arm64&#xff0c;而不是传统PC的amd64&#xff0c;深度学习的环境配置方法…

chatgpt赋能python:Python对接技术在SEO中的应用

Python对接技术在SEO中的应用 Python作为一种高性能的编程语言&#xff0c;被广泛应用于各种领域&#xff0c;其中也包括了搜索引擎优化&#xff08;SEO&#xff09;领域。Python对接技术&#xff0c;也称为API对接技术&#xff0c;是指通过调用API接口来获取数据、信息或实现…

AI数字人打造之sadtalker让照片开口说话

1 sadtalker介绍 西安交通大学也开源了人工智能SadTalker模型&#xff0c;通过从音频中学习生成3D运动系数&#xff0c;使用全新的3D面部渲染器来生成头部运动&#xff0c;可以实现图片音频就能生成高质量的视频。 论文地址&#xff1a;Learning Realistic 3D Motion Coefficie…

chatgpt赋能python:Python屏蔽语句的重要性

Python屏蔽语句的重要性 Python是一种高级程序设计语言&#xff0c;被认为是开发Web应用程序、数据科学和人工智能的最佳语言之一。在编写Python程序时&#xff0c;每个人都会遇到需要屏蔽语句的情况。在本文中&#xff0c;我们将详细介绍Python屏蔽语句的重要性和用法。 什么…

chatgpt赋能python:Python建模仿真:优秀的工具与技巧

Python建模仿真&#xff1a;优秀的工具与技巧 在现代科技时代&#xff0c;建模仿真是许多不同行业的核心部分&#xff0c;帮助工程师和科学家研究解决许多问题。Python作为一种简单易学且强大的语言&#xff0c;已经被广泛应用于建模仿真领域。 Python的优点 Python在建模仿…

用Python进行数学建模(一)

一、导入数据 1.直接赋值 2.读取 Excel 文件 3.代码示例 import pandas as pd# 读取数据文件 def readDataFile(readPath): # readPath: 数据文件的地址和文件名try:if (readPath[-4:] ".csv"):dfFile pd.read_csv(readPath, header0, sep",") # 间隔…

chatgpt赋能python:Python嵌入C:一个高效的编程技巧

Python嵌入C&#xff1a;一个高效的编程技巧 作为一名有10年Python编程经验的工程师&#xff0c;我发现在某些情况下&#xff0c;Python嵌入C是一种高效的编程技巧。这种技巧可以使您利用Python的简洁性和高级功能&#xff0c;同时仍然保持程序的执行速度。在本文中&#xff0…

chatgpt赋能python:Python对接硬件:从入门到精通

Python对接硬件&#xff1a;从入门到精通 Python是一门极为强大的编程语言&#xff0c;它不只是用来进行数据分析和Web开发的&#xff0c;也可以用来对接各种硬件设备。这是因为Python具有简单易学&#xff0c;语法简洁&#xff0c;库众多的优点。 什么是Python对接硬件 Pyt…

通过AI工具(ChatGPT接口)生成一字未改的论文,查重率4.2%,可以直接当作论文使用

论文题目&#xff1a;基于AIOT技术的能源控制器的设计以及应用 查重结果&#xff1a;4.2% AI工具国内体验&#xff0c;关注&#xff1a;码视野&#xff0c;回复关键字&#xff1a;1002 一、引言 随着全球经济的快速发展和人口的增长&#xff0c;对能源的需求日益增加。然而&…

nodejs环境变量配置问题记录

问题一&#xff1a;Error: EPERM: operation not permitted, open ‘D:\Program Files\nodejs\node_cache\_cacache\tmp\bccd20 这个问题主要是没有权限导致的。 问题二&#xff1a;使用node命令提示 ‘node‘ 不是内部或外部命令&#xff0c;也不是可运行的程序 这个错误是环…

chatgpt赋能python:Python如何将文件另存为:让您的文件管理更便捷

Python如何将文件另存为&#xff1a;让您的文件管理更便捷 随着数字化时代的来临&#xff0c;文件管理已经成为我们日常工作不可缺少的一部分。当涉及到大量的文件管理时&#xff0c;手动操作可能会浪费大量的时间和精力。 在这种情况下&#xff0c;自动化的解决方案将会是很有…

【玩转Linux操作】用户管理(命令讲解配上样例解释)

&#x1f38a;专栏【玩转Linux操作】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Counting Stars 】 欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f354;添加用户⭐命令&#x1f388;useradd 用户名 ⭐演示…