ShardingSphere

高性能架构模式

  • 互联网业务兴起之后,海量用户加上海量数据的特点,单个数据库服务器已经难以满足业务需要,必须考虑数据库集群的方式来提高性能。高性能数据库集群的第一种方式是“读写分离”,第二种方式是“数据库分片”

  • 读写分离架构
    • 读写分离的基本原理是将数据库读写操作分散到不同的节点上

  • 读写分离的基本实现
    • 主库负责处理事务性的增删改查,从库负责处理查询操作,能够有效的避免由数据库更新导致的行锁,使得整个系统的查询性能得到极大的改善
    • 读写分离是根据SQL语义的分析,将读操作和写操作分别路由至主库与从库
    • 通过一主多从的配置方式,可以将查询请求均匀的分散到多个数据副本,能够进一步的提升系统的处理能力。
    • 使用多主多从的方式,补单能够提升系统的吞吐量,还能够提升系统的可用性,可以达到在任何一个数据库宕机,甚至磁盘物理损坏的情况下仍然不影响系统的正常运行

  • CAP理论
    • CAP理论(CAP theorem)又被称作布鲁尔定理(Brewer's theorem),是加州大学伯克分校的计算机科学家埃里克.布鲁尔(Eric Brewer)在2000年ACM PODC上提出的一个猜想。

  • 在一个分布式系统中,当涉及读写操作时,只能保证一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三者中的两个,另外一个必须牺牲
    • C一致性:对某个指定的客户端来说,读操作保证能够返回最新的操作结果
    • A可用性:非故障的节点在合理的时间内返回合理的响应
    • P分区容灾性:当出现网络分区后,系统能够继续运行

  • CAP特点
    • 在实际设计过程中,每个系统不可能只处理一种数据,而是包含多种类型的数据,有的数据必须选择CP,有的数据必须选择AP,分布式系统理论上不可能选择CA架构
  • CP:如下图所示,为了保证一致性,当发生分区线程后N1节点的数据已经更新到y,但由于N1和N2之间的复制通道中断,数据y无法同步到N2,N2节点上的数据还是x。这时客户端C访问N2时,N2需要返回Error,提示客户端C"系统发生了错误",这种处理方式违背了可用性的要求,因此CAP三者只能满足CP

  • AP:如下图所示,为了保证可用性,当发生分区现象后,N1节点上的数据已经更新到y,但由于N1和N2之间的复制通道中断,数据y无法同步到N2,N2节点上的数据还是x。这时客户端C访问N2时,N2将自己拥有的数据x返回给客户端C了,而实际上当前最新的数据已经是y了,这就不满足一致性的要求了,因此CAP三者只能满足AP。注意:这里N2节点返回x,虽然不是一个“正确”的结果,因为x是旧的数据,并不是一个错乱的值,只是不是最新的数据而已


  • 数据库分片架构
  • 读写分离问题
    • 读写分离分散了数据库读写操作的压力,但没有分散存储压力,为了满足业务数据存储需求,就需要将存储分散到多台数据库服务器上
  • 数据分片
    • 将存放在单一数据库中的数据分散地存放至多个数据库或表中,以达到提升性能瓶颈以及可用性的效果。数据分片的有效手段是对关系型数据库进行分库和分表。数据分片的拆分方式又分为垂直拆分和水平拆分

  • 垂直分片
    • 垂直分库
      • 按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分散到不同的数据库中,从而将压力分散至不同的数据库
    • 垂直分表
      • 垂直分表适合将表中某些不常用的列,或者是占了大量空间的列拆分出去
      • 假设我们是一个婚恋网站,用户在筛选其他用户的时候,主要是用age和sex两个字段进行查询,而nickname和description两个字段主要用于展示,一般不会在业务查询中用到。description本身又比较长,因此我们可以将这两个字段独立到另外一张表中,这样在查询age和sex时,就能带来一定的性能提升
      • 垂直分表引用的复杂性主要体现在表操作的数量要增加,例如,原来只要一次查询就可以获取name、age、sex、nickname、description,现在需要两次查询,一次查询获取name、age、sex,另外一次查询获取nickname、description

  • 水平分片
    • 水平分片又称为横向拆分。相对于垂直分片,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分。例如:根据主键分片,偶数主键的记录放入0库(或表),奇数主键的记录放入1库(或表)
    • 水平分表
      • 单表切分为多表后,新的表即使在同一个数据库服务器中,也可能带来可观的性能提升,如果性能能够满足业务要求,可以不拆分到多态数据库服务器,毕竟业务分库会引入很多复杂性
      • 水平分库
        • 如果单表拆分为多表后,单台服务器依然无法满足性能要求,那就需要将多个表分散在不同的数据库服务器中

  • 实现方式
  • 程序代码封装
    • 程序代码封装指在代码中抽象一个数据访问层(或中间层封装),实现读写操作分离和数据库服务器连接的管理

  • 中间件封装
    • 中间件封装指的是独立一套系统出来,实现读写操作分离和数据库服务器连接的管理。对于业务服务器来说,访问中间件和访问数据库没有区别,在业务服务器看来,中间件就是一个数据库服务器

  • 常用的解决方案
    • Apache ShardingSphere(程序级别和中间件级别)
    • MyCat(数据库中间件)

ShardingSphere


  • ShardingSphere-JDBC
    • 程序代码封装
    • 定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架

  • ShardingSphere-Proxy
    • 中间件封装
    • 定位为透明的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。目前提供MySQL和PostgreSQL版本,它可以使用任何兼容MySQL/PostgreSQL协议的访问客户端(如MYSQL Command Client,MySQL Workbench,Navicat等)操作数据,对DBA更加友好

MySQL主从同步

  • MySQL主从同步原理

  • 基本原理

    • slave会从master读取binlog来进行数据同步
  • 具体步骤

    1. master将数据改变记录到二进制日志(binary log)中
    2. 当slave上执行start slave命令之后,slave会创建一个IO线程用来连接master,请求master中的binlog
    3. 当slave连接master时,master会创建一个log dump线程,用于发送binlog的内容。在读取binlog的内容操作中,会对主节点上的binlog加锁,当读取完成并发送给从服务器后解锁
    4. IO线程接收主节点binlog dump进程发来更新之后,保存到中继日志(relay log)中
    5. slave的SQL线程,读取relay log日志,并解析成具体操作,从而实现主从操作一致,最终数据一致。
  • 一主多从配置

    • 使用docker方式创建,主从服务器IP一致,端口号不一致

  • 创建主服务器master
docker run -d \
-p 3306:3306 \
-v /root/mysql/master/conf:/etc/mysql/conf.d \
-v /root/mysql/master/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name atguigu-mysql-master \
mysql:8.0.29
  • 编写主服务器配置文件/root/mysql/master/conf/my.cnf
[mysqld]
# 服务器唯一id,默认值1
server-id=1
# 设置日志格式,默认值ROW
binlog_format=STATEMENT
# 二进制日志名,默认binlog
# log-bin=binlog
# 设置需要复制的数据库,默认复制全部数据库
#binlog-do-db=mytestdb
# 设置不需要复制的数据库
#binlog-ignore-db=mysql
#binlog-ignore-db=infomation_schema
  • binlog_format说明
    • binlog_format=STATEMENT:日志记录的是主机数据库的写指令,性能高,但是now()之类的函数以及获取系统参数的操作会出现主从数据不同步问题
    • binlog_format=ROW(默认):日志记录的是主机数据库的写后的数据,批量操作时性能较差,解决now()之类函数操作在主从机器上不一致问题
    • binlog_format=MIXED:是以上两种level的混合使用,有函数用ROW,没有函数用STATEMENT,但是无法识别系统变量
  • 重启MySQL容器
  • 主机中创建slave用户
-- 创建slave用户
CREATE USER 'atguigu_slave'@'%';
-- 设置密码
ALTER USER 'atguigu_slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'atguigu_slave'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
  • 主机中查询master状态
show master status;

  • 创建从服务器
docker run -d \
-p 3307:3306 \
-v /root/mysql/slave1/conf:/etc/mysql/conf.d \
-v /root/mysql/slave1/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name atguigu-mysql-slave1 \
mysql:8.0.29
  • 创建mysql从服务器配置文件 /root/mysql/slave1/conf/my.cnf
[mysqld]
# 服务器唯一id,每台服务器的id必须不同,如果配置其他从机,注意修改id
server-id=2
# 中继日志名,默认xxxxxxxxxxxx-relay-bin
#relay-log=relay-bin
  • 重启MySQL容器
docker restart atguigu-mysql-slave1
  • 在从机上配置主从关系
CHANGE MASTER TO MASTER_HOST='172.16.0.150', 
MASTER_USER='atguigu_slave',MASTER_PASSWORD='123456', MASTER_PORT=3306,
MASTER_LOG_FILE='binlog.000003',MASTER_LOG_POS=1378; 
  • 启动主从同步
start slave;
  • 按照同样的方式创建slave2从服务器
  • 停止和重置
-- 在从机上执行。功能说明:停止I/O 线程和SQL线程的操作。
stop slave; 

-- 在从机上执行。功能说明:用于删除SLAVE数据库的relaylog日志文件,并重新启用新的relaylog文件。
reset slave;

-- 在主机上执行。功能说明:删除所有的binglog日志文件,并将日志索引文件清空,重新开始所有新的日志文件。
-- 用于第一次进行搭建主从库时,进行主库binlog初始化工作;
reset master;

ShardingSphere-JDBC读写分离

  • 创建SpringBoot项目
  • 添加maven依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
        <version>5.1.1</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.1</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
  • 配置文件
# 应用名称
spring.application.name=sharding-jdbc
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory

# 配置真实数据源
spring.shardingsphere.datasource.names=master,slave1,slave2

# 配置第 1 个数据源
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://172.16.0.150:3306/db_user
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=123456

# 配置第 2 个数据源
spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://172.16.0.150:3307/db_user
spring.shardingsphere.datasource.slave1.username=root
spring.shardingsphere.datasource.slave1.password=123456

# 配置第 3 个数据源
spring.shardingsphere.datasource.slave2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave2.jdbc-url=jdbc:mysql://172.16.0.150:3308/db_user
spring.shardingsphere.datasource.slave2.username=root
spring.shardingsphere.datasource.slave2.password=123456

# 读写分离类型,如: Static,Dynamic
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.type=Static
# 写数据源名称
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.props.write-data-source-name=master
# 读数据源名称,多个从数据源用逗号分隔
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.props.read-data-source-names=slave1,slave2
#
## 负载均衡算法名称
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.load-balancer-name=alg_round
#
## 负载均衡算法配置
## 负载均衡算法类型
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_round.type=ROUND_ROBIN
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_random.type=RANDOM
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.type=WEIGHT
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.props.slave1=1
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.props.slave2=2
#
## 打印SQl
spring.shardingsphere.props.sql-show=true
  • 实体类User
@TableName("t_user")
@Data
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String uname;
}
  • UserMapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
  • 读写分离测试
@SpringBootTest
public class ReadWriteTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void readWriteTest(){
        User user = new User();
        user.setUname("zhangsan");
        userMapper.insert(user);
        List<User> users = userMapper.selectList(null);
    }
}

  • 事务测试
    • 为了保证主从库间事务一致性,避免跨服务的分布式事务,ShardingSphere-JDBC主从模型中,事务中的数据读写均用主库
    • 不添加@Transaction:insert对主库操作,select对从库操作
    • 添加@Transaction:则insert和select均对主库操作
    @Test
    @Transactional
    public void readWriteTest(){
        User user = new User();
        user.setUname("zhangsan");
        userMapper.insert(user);
        List<User> users = userMapper.selectList(null);
    }

ShardingSphere-JDBC垂直分片(分库)

  • 准备服务器
    • 服务器:容器名server-user,端口3301
    • 服务器:容器名server-order,端口3302

  • user
docker run -d \
-p 3301:3306 \
-v /root/mysql/user/conf:/etc/mysql/conf.d \
-v /root/mysql/user/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-user \
mysql:8.0.29
  • 创建数据库和表
CREATE DATABASE db_user;
USE db_user;
CREATE TABLE t_user (
 id BIGINT AUTO_INCREMENT,
 uname VARCHAR(30),
 PRIMARY KEY (id)
);
  • order
docker run -d \
-p 3302:3306 \
-v /root/mysql/order/conf:/etc/mysql/conf.d \
-v /root/mysql/order/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order \
mysql:8.0.29
  • 创建数据库和表
CREATE DATABASE db_order;
USE db_order;
CREATE TABLE t_order (
  id BIGINT AUTO_INCREMENT,
  order_no VARCHAR(30),
  user_id BIGINT,
  amount DECIMAL(10,2),
  PRIMARY KEY(id) 
);
  • 配置文件
# 应用名称
spring.application.name=sharding-jdbc
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory

# 配置真实数据源
spring.shardingsphere.datasource.names=server-user,server-order

# 配置第 1 个数据源
spring.shardingsphere.datasource.server-user.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-user.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-user.jdbc-url=jdbc:mysql://172.16.0.150:3301/db_user
spring.shardingsphere.datasource.server-user.username=root
spring.shardingsphere.datasource.server-user.password=123456

# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order.jdbc-url=jdbc:mysql://172.16.0.150:3302/db_order
spring.shardingsphere.datasource.server-order.username=root
spring.shardingsphere.datasource.server-order.password=123456

# 垂直分片
# 由数据源名+表名组成,多个表以逗号隔开 支持inline表达式
spring.shardingsphere.rules.sharding.tables.t_user.actual-data-nodes=server-user.t_user
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order.t_order

## 打印SQl
spring.shardingsphere.props.sql-show=true
  • 测试
    @Test
    public void insertOrderAndUser(){
        User user = new User();
        user.setUname("zhangsan");
        userMapper.insert(user);

        Order order = new Order();
        order.setOrderNo("order-001");
        order.setUserId(user.getId());
        order.setAmount(new BigDecimal(100));
        orderMapper.insert(order);
    }
  • sql日志

ShardingSphere-JDBC水平分片

  • 容器名server-order0,端口3301
  • 容器名server-order1,端口3311

  • 创建server-order0
docker run -d \
-p 3310:3306 \
-v /root/mysql/order0/conf:/etc/mysql/conf.d \
-v /atguigu/server/order0/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order0 \
mysql:8.0.29
  • 创建数据库
CREATE DATABASE db_order;
USE db_order;
CREATE TABLE t_order0 (
  id BIGINT,
  order_no VARCHAR(30),
  user_id BIGINT,
  amount DECIMAL(10,2),
  PRIMARY KEY(id) 
);
CREATE TABLE t_order1 (
  id BIGINT,
  order_no VARCHAR(30),
  user_id BIGINT,
  amount DECIMAL(10,2),
  PRIMARY KEY(id) 
);
  • 创建server-order1

docker run -d
-p 3311:3306
-v /root/mysql/order1/conf:/etc/mysql/conf.d
-v /root/mysql/order1/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456
--name server-order1
mysql:8.0.29

  • 创建数据库
CREATE DATABASE db_order;
USE db_order;
CREATE TABLE t_order0 (
  id BIGINT,
  order_no VARCHAR(30),
  user_id BIGINT,
  amount DECIMAL(10,2),
  PRIMARY KEY(id) 
);
CREATE TABLE t_order1 (
  id BIGINT,
  order_no VARCHAR(30),
  user_id BIGINT,
  amount DECIMAL(10,2),
  PRIMARY KEY(id) 
);
  • 配置文件
# 应用名称
spring.application.name=sharding-jdbc
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory

# 配置真实数据源
spring.shardingsphere.datasource.names=server-user,server-order0,server-order1

# 配置第 1 个数据源
spring.shardingsphere.datasource.server-user.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-user.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-user.jdbc-url=jdbc:mysql://172.16.0.150:3301/db_user
spring.shardingsphere.datasource.server-user.username=root
spring.shardingsphere.datasource.server-user.password=123456

# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order0.jdbc-url=jdbc:mysql://172.16.0.150:3310/db_order
spring.shardingsphere.datasource.server-order0.username=root
spring.shardingsphere.datasource.server-order0.password=123456

# 配置第 3 个数据源
spring.shardingsphere.datasource.server-order1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order1.jdbc-url=jdbc:mysql://172.16.0.150:3311/db_order
spring.shardingsphere.datasource.server-order1.username=root
spring.shardingsphere.datasource.server-order1.password=123456

#--------------标准分片配置--------------
# 将t_user表对象路由到server-user数据源的t_user表
# 将t_order表对象路由到server_order0数据源的t_order0表、t_order1表,server_order1数据源的t_order0表、t_order1表
# 由数据源名+表名组成,多个表以逗号隔开 支持inline表达式
spring.shardingsphere.rules.sharding.tables.t_user.actual-data-nodes=server-user.t_user
#spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order0.t_order0,server-order0.t_order1,server-order1.t_order0,server-order1.t_order1
#inline 表达式
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order$->{0..1}.t_order$->{0..1}


#--------------分库策略--------------
# 分片列名称,根据user_id字段进行分库
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_userid

#--------------分片算法配置--------------
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.type=INLINE
# 分片算法属性配置,user_id对2取余,偶数路由到server_order0,奇数路由到server_order1
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.props.algorithm-expression=server-order$->{user_id % 2}

# 取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2


#------------------------分表策略
# 分片列名称,根据order_no字段进行分表
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod


#------------------------分片算法配置
# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2

## 打印SQl
spring.shardingsphere.props.sql-show=true
  • 测试
    @Test
    public void shardingTest(){
        /**
         * userId为1则会被路由到server_order1数据源
         * orderNo根据hashcode对2取余路由到t_order0或t_order1
         */
        for (int i = 1; i <= 4; i++) {
            Order order = new Order();
            order.setUserId(1L);
            order.setOrderNo("100"+i);
            order.setAmount(new BigDecimal(100));
            orderMapper.insert(order);
        }

        /**
         * userId为2则会被路由到server_order0数据源
         * orderNo根据hashcode对2取余路由到t_order0或t_order1
         */
        for (int i = 5; i <= 8; i++) {
            Order order = new Order();
            order.setUserId(2L);
            order.setOrderNo("100"+i);
            order.setAmount(new BigDecimal(100));
            orderMapper.insert(order);
        }
    }
  • ShardingSphere分布式Id配置
#------------------------分布式序列策略配置
# 分布式序列列名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=alg_snowflake

# 分布式序列算法类型
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE
# 分布式序列算法属性配置 id不是分片属性,下面可以不配置
# spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.props.xxx=
  • 修改Order对象id生成策略
@TableName("t_order")
@Data
public class Order {
    /**
     * 当配置了shardingSphere的分布式事务时,自动使用shardingSphere-jdbc的分布式序列
     * 在没有配置shardingSpere-jdbc的序列时候,自动依赖数据库的主键自增策略
     */
    @TableId(type = IdType.AUTO)
    //@TableId(type = IdType.ASSIGN_ID) //mybatis plus分布式id(默认)
    private Long id;

    private String orderNo;

    private Long userId;

    private BigDecimal amount;
}
posted @ 2023-01-11 09:38  youmo~  阅读(176)  评论(0编辑  收藏  举报