Apache ShardingSphere-JDBC基本教程

Apache ShardingSphere-JDBC基本教程

Apache ShardingSphere是分布式的数据库生态系统,可以将任意数据库转换为分布式数据库。
同时可以通过对数据进行分片、弹性伸缩、加密等功能来对原有的数据库进行增强。

ShardingSphere主要包含三个模块:

  • ShardingSphere-JDBC:轻量级的Java框架,在Java的JDBC层提供额外服务
  • ShardingSphere-Proxy:透明化的数据库代理端,通过实现数据库二进制协议,对异构语言提供支持。
  • ShardingSphere-sidecar:定位为k8s的云原生数据库代理【目前还在规划中】

官网地址:
https://shardingsphere.apache.org/document/current/cn/overview/

1 前置知识

1.1 高性能架构模式

①读写分离架构
在这里插入图片描述
在一个分布式系统中,当涉及读写操作时,只能保证一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三者中的两个,另外一个必须被牺牲。

  • C 一致性(Consistency):对某个指定的客户端来说,读操作保证能够返回最新的写操作结果
  • A 可用性(Availability):非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)
  • P 分区容忍性(Partition Tolerance):当出现网络分区后(可能是丢包,也可能是连接中断,还可能是拥塞),系统能够继续“履行职责”

CA在分布式系统中是无法同时满足的,因为是读写分离,如果此时从机在复制主机上的新数据的时候,用户需要查询数据来访问从机:

  1. 如果我们选择返回数据,那么就保证了可用性(A),但是一致性(C)没有保证,因为用户拿到的数据不是最新的
  2. 如果选择不返回数据,那么就没有保证可用性,而选择了一致性

②数据库分片架构

读写分离分散了数据库读写操作的压力,但没有分散存储压力,为了满足业务数据存储的需求,就需要将存储分散到多台数据库服务器上

数据分片:

将存放在单一数据库中的数据分散地存放至多个数据库或表中,以达到提升性能瓶颈以及可用性的效果。 数据分片的有效手段是对关系型数据库进行分库和分表。数据分片的拆分方式又分为垂直分片和水平分片

  1. 垂直分片【纵向拆分】
  1. 垂直分库:例如:用户数据库、订单库、商品数据库
  2. 垂直分表:按照表的字段拆分,比如把nickname、description…又重新分为一个表【拆分后所有表的id一样,采用策略一样】
  1. 水平分片【垂直拆分】
  1. 水平分库:例如:将订单数据存放在多个数据库中
  2. 水平分表:将一张表的数据存放在多个订单表中
阿里巴巴Java开发手册:

【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。

说明:如果预计三年后的数据量根本达不到这个级别,`请不要在创建表时就分库分表`。

③读写分离和数据分片架构
在这里插入图片描述
架构演变过程

1.2 实现方式

  1. 程序代码封装

在代码中实现读写分离和数据库连接管理

在这里插入图片描述

  1. 中间件封装

独立一套系统出来,实现读写分离和数据库服务连接的管理。

在这里插入图片描述

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

1.3 主从同步原理

在这里插入图片描述

slave会从master读取binlog来进行数据同步

具体步骤:

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

2 Sharding-JDBC

增强版的JDBC驱动,访问任意数据库

在这里插入图片描述

2.1 Sharding-JDBC实现读写分离

此处我使用的是docker创建三个容器来实现数据库的主从
基于docker实现数据库的主从

①创建项目,导入依赖

 <dependencies>
     <!--导入web模块-->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>

     <!--导入sharding依赖-->
     <dependency>
         <groupId>org.apache.shardingsphere</groupId>
         <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
         <version>5.1.1</version>
     </dependency>

     <!--导入mysql依赖-->
     <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <scope>runtime</scope>
     </dependency>

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

     <!--lombok:简化实体类开发-->
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <optional>true</optional>
     </dependency>

     <!--test依赖-->
     <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>

②配置文件
application.properties格式:

# 应用名称
spring.application.name=sharding-jdbc-demo
# 开发环境设置
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.cj.jdbc.Driver
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://192.168.145.48: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.cj.jdbc.Driver
spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://192.168.145.48: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.cj.jdbc.Driver
spring.shardingsphere.datasource.slave2.jdbc-url=jdbc:mysql://192.168.145.48: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

application.yml:

spring:
  application:
    name: sharding-jdbc
  profiles:
    active: dev
  shardingsphere:
    mode:
      type: Memory
    datasource:
      names: master,slave1,slave2
      master:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.145.48:3306/db_user
        username: root
        password: 123456
      slave1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.145.48:3307/db_user
        username: root
        password: 123456
      slave2:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.145.48:3308/db_user
        username: root
        password: 123456
    rules:
      readwrite-splitting:
        data-sources:
          myds:
            type: Static
            props:
              write-data-source-name: master
              read-data-source-names: slave1,slave2
            load-balancer-name: alg_round
        load-balancers:
          alg_round:
            type: ROUND_ROBIN
    props:
      sql-show: true

properties与yml二者选其一即可

2.1.1 测试主从同步
  1. 添加实体类与mapper:

User:

@Data
@TableName(value = "t_user")
public class User {

    //因为在创建表的时候使用了主键自增,所以这里采用id自增
    @TableId(type = IdType.AUTO)
    private Long id;

    private String uname;
}

UserMapper:

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

  1. 测试类
@SpringBootTest
public class Test01 {

    @Autowired
    private UserMapper userMapper;

    @Test
    void testInsert(){
        User user = new User();
        user.setUname("徐杰");
        userMapper.insert(user);
    }
}

查看不同数据库中的表数据:

  • master:
    在这里插入图片描述
  • slave1:
    在这里插入图片描述
  • slave2:
    在这里插入图片描述
2.1.2 测试读写分离
@Test
void testInsert(){
    User user = new User();
    user.setUname("内马尔");
    userMapper.insert(user);
    List<User> users = userMapper.selectList(null);
}

在这里插入图片描述

可以看到插入操作,操作的是master;查询操作,操作的是slave从库

2.1.3 测试事务

为了保证主从库间的事务一致性,避免跨服务的分布式事务,ShardingSphere-JDBC的主从模型中,事务中的数据读写均用主库

  • 不添加@Transactional:insert对主库操作,select对从库操作
  • 添加@Transactional:则insert和select均对主库操作
  • 注意 :在JUnit环境下的@Transactional注解,默认情况下就会对事务进行回滚(即使在没加注解@Rollback,也会对事务回滚)
/**
 * 不添加@Transactional:insert对主库操作,select对从库操作
 * 添加@Transactional:insert、select都在主库上操作
 */
@Transactional
@Test
void testTrans(){
    User user = new User();
    user.setUname("C罗");
    userMapper.insert(user);
    List<User> users2 = userMapper.selectList(null);
}
  • 不添加@Transactional:
    在这里插入图片描述
  • 添加@Transactional:
    在这里插入图片描述

注意:Sharding-JDBC也可以实现负载均衡算法,只需要在配置文件中配置即可

# 负载均衡算法配置
# 负载均衡算法类型
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

2.2 Sharding-JDBC实现垂直分片

首先,我们之前是基于docker创建的MySQL主从,因此需要先停止前面的docker容器
如果不会创建docker容器的参考:https://editor.csdn.net/md/?articleId=127551457

停止之前的docker容器(避免内存消耗):
在这里插入图片描述
①创建新的docker容器
在这里插入图片描述

  • 服务器:容器名server-user,端口3301

  • 服务器:容器名server-order,端口3302

① 创建server-user容器
  • 创建容器:
docker run -d \
-p 3301:3306 \
-v /zi/server/user/conf:/etc/mysql/conf.d \
-v /zi/server/user/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-user \
mysql:8.0.31
  • 登录MySQL服务器
#进入容器:
docker exec -it server-user env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
#修改默认密码插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
  • 创建用户数据库
CREATE DATABASE db_user;
USE db_user;
CREATE TABLE t_user (
 id BIGINT AUTO_INCREMENT,
 uname VARCHAR(30),
 PRIMARY KEY (id)
);
②创建server-order容器
  • 创建容器
docker run -d \
-p 3302:3306 \
-v /zi/server/order/conf:/etc/mysql/conf.d \
-v /zi/server/order/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order \
mysql:8.0.31
  • 登录容器中的MySQL服务器
#进入容器:
docker exec -it server-order env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
#修改默认密码插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
  • 创建order数据库
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) 
);
③程序实现-SpringBoot

导入依赖于上文一样

  • 定义实体类与mapper
    Order:
@TableName("t_order")
@Data
public class Order {

    @TableId(type = IdType.AUTO)
    private Long id;
    /**
     * MP默认帮助我们_转驼峰
     */
    private String orderNo;
    private Long userId;
    private BigDecimal amount;
}

User:

@Data
@TableName(value = "t_user")
public class User {

    //因为在创建表的时候使用了主键自增,所以这里采用id自增
    @TableId(type = IdType.AUTO)
    private Long id;

    private String uname;
}

OrderMapper:

@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}

UserMapper:

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

  • 测试垂直分片
    /**
     * 垂直分片:插入数据测试
     */
    @Test
    void testInsertOrderAndUser(){
        User user = new User();
        user.setUname("强哥");
        userMapper.insert(user);

        Order order = new Order();
        order.setOrderNo("ZI001");
        order.setUserId(user.getId());
        order.setAmount(new BigDecimal(100));
        orderMapper.insert(order);
    }

    /**
     * 垂直分片:查询数据测试
     */
    @Test
    void testSelectFromOrderAndUser(){
        User user = userMapper.selectById(1L);
        Order order = orderMapper.selectById(1L);
    }

在这里插入图片描述

插入订单去操作t_order,插入用户操作t_user,可以看到实现垂直分片成功

常见错误:
在这里插入图片描述
ShardingSphere-JDBC远程连接的方式默认的密码加密规则是:mysql_native_password

因此需要在服务器端修改服务器的密码加密规则,如下:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

2.3 Sharding-JDBC实现水平分片

将之前的server-order容器停止

docker stop server-order

server-order容器规划
在这里插入图片描述

  • 服务器:容器名server-order0,端口3310

  • 服务器:容器名server-order1,端口3311

①创建server-order0容器
  • 创建容器
docker run -d \
-p 3310:3306 \
-v /zi/server/order0/conf:/etc/mysql/conf.d \
-v /zi/server/order0/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order0 \
mysql:8.0.31
  • 登录服务器
#进入容器:
docker exec -it server-order0 env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
#修改默认密码插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
  • 创建数据库

注意:水平分片的id需要在业务层实现,不能依赖数据库的主键自增

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 /zi/server/order1/conf:/etc/mysql/conf.d \
-v /zi/server/order1/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order1 \
mysql:8.0.
  • 登录容器中的MySQL
#进入容器:
docker exec -it server-order1 env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
#修改默认密码插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

-创建数据库

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) 
);
③程序实现
  1. 修改order实体类,将自增改为ASSIGN_ID

order:

@TableName("t_order")
@Data
public class Order {

    //@TableId(type = IdType.AUTO)//依赖数据库的主键自增策略
    @TableId(type = IdType.ASSIGN_ID)//分布式id
    private Long id;
    /**
     * MP默认帮助我们_转驼峰
     */
    private String orderNo;
    private Long userId;
    private BigDecimal amount;
}

  1. 配置文件
#========================基本配置
# 应用名称
spring.application.name=sharging-jdbc
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory
# 打印SQl
spring.shardingsphere.props.sql-show=true

#========================数据源配置
# 配置真实数据源
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://192.168.145.48: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://192.168.145.48: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://192.168.145.48:3311/db_order
spring.shardingsphere.datasource.server-order1.username=root
spring.shardingsphere.datasource.server-order1.password=123456


#========================标准分片表配置(数据节点配置)
# spring.shardingsphere.rules.sharding.tables.<table-name>.actual-data-nodes=值
# 值由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# <table-name>:逻辑表名
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$->{0..1}.t_order$->{0..1}
#spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order$->{0..1}.t_order$->{0..1} #会进行笛卡尔积【需要指定表名称,否则会报错】


#------------------------分库策略
# 分片列名称【针对user_id对2取模】
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_mod

#------------------------分表策略
# 分片列名称
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_inline_userid.type=INLINE
# 分片算法属性配置
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


# ③哈希取模分片算法
# 分片算法类型
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

官网数据分片配置地址

此处我们分库采用取模算法,分表采用hash取模算法

  1. 测试类
/**
* 水平分片:分库分表插入数据测试
* [根据orderNo和userId来决定是插入哪个数据库的哪个表]
*/
@Test
public void testInsertOrderDatabaseStrategy(){

   for (long i = 0; i < 4; i++) {
       Order order = new Order();
       order.setOrderNo("ZI00000");//注意:是根据HASH值取模,也就是.hashCode,而不是仅仅看末尾值
       order.setUserId(i + 1);
       order.setAmount(new BigDecimal(100));
       orderMapper.insert(order);
   }

   for (long i = 0; i < 4; i++) {
       Order order = new Order();
       order.setOrderNo("ZI00001");
       order.setUserId(i + 1);
       order.setAmount(new BigDecimal(100));
       orderMapper.insert(order);
   }

}
  1. 结果
    【1】server-order0的t_order0表:
    在这里插入图片描述
    【2】server-order0-t_order1表:
    在这里插入图片描述
    【3】server-order1-t_order0表:

在这里插入图片描述

【4】server-order1-t_order1表:
在这里插入图片描述

水平分片的查询

查询了两个数据源,每个数据源中使用UNION ALL连接两个表

/**
 * 水平分片:【分库、分表】
 * 查询所有订单,查询两个数据源(server-order0、server-order1),同一个数据库的不同表(t_order0、t_order1查询结果使用UNION ALL连接)
 */
@Test
public void testShardingSelectAll(){

    List<Order> orders = orderMapper.selectList(null);
    orders.forEach(System.out::println);
}

在这里插入图片描述
控制台打印:

Logic SQL: SELECT  id,order_no,user_id,amount  FROM t_order
SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
Actual SQL: server-order0 ::: SELECT  id,order_no,user_id,amount  FROM t_order0 UNION ALL SELECT  id,order_no,user_id,amount  FROM t_order1
Actual SQL: server-order1 ::: SELECT  id,order_no,user_id,amount  FROM t_order0 UNION ALL SELECT  id,order_no,user_id,amount  FROM t_order1
分布式序列- snowflake

官网:https://shardingsphere.apache.org/document/5.1.1/cn/user-manual/shardingsphere-jdbc/builtin-algorithm/keygen/

  1. 修改Order
@TableName("t_order")
@Data
public class Order {

    //当配置了shardingsphere-jdbc的分布式序列时,自动使用shardingsphere-jdbc的分布式序列
    //当没有配置shardingsphere-jdbc的分布式序列时,自动依赖数据库的主键自增策略
    @TableId(type = IdType.AUTO)
//    @TableId(type = IdType.ASSIGN_ID)//分布式id【MyBatisPlus默认】
    private Long id;
    /**
     * MP默认帮助我们_转驼峰
     */
    private String orderNo;
    private Long userId;
    private BigDecimal amount;
}
  1. 在application.properties添加配置
    在这里插入图片描述

官网配置:https://shardingsphere.apache.org/document/5.1.1/cn/user-manual/shardingsphere-jdbc/spring-boot-starter/rules/sharding/

#-----------------分布式序列配置【雪花算法】
# 配置分布式序列
    # 分片列名称
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
    # 分布式序列算法属性配置【此处我们没有使用分片列,因此该属性可以不用配置】
#spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.props.xxx=
  1. 测试
 @Test
 public void testKeyGenerator(){
     Order order = new Order();
     order.setUserId(1L);
     order.setAmount(new BigDecimal(50));
     order.setOrderNo("ZI412341");
     orderMapper.insert(order);
 }
  1. 结果
    在这里插入图片描述

3 Sharding-Proxy

中间件封装, 使用任意语言

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值