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在分布式系统中是无法同时满足的,因为是读写分离,如果此时从机在复制主机上的新数据的时候,用户需要查询数据来访问从机:
- 如果我们选择返回数据,那么就保证了可用性(A),但是一致性(C)没有保证,因为用户拿到的数据不是最新的
- 如果选择不返回数据,那么就没有保证可用性,而选择了一致性
②数据库分片架构
读写分离分散了数据库读写操作的压力,但没有分散存储压力,为了满足业务数据存储的需求,就需要
将存储分散到多台数据库服务器上
。
数据分片:
将存放在单一数据库中的数据分散地存放至多个数据库或表中,以达到提升性能瓶颈以及可用性的效果。 数据分片的有效手段是对关系型数据库进行分库和分表
。数据分片的拆分方式又分为垂直分片和水平分片
。
- 垂直分片【纵向拆分】
- 垂直分库:例如:用户数据库、订单库、商品数据库
- 垂直分表:按照表的字段拆分,比如把nickname、description…又重新分为一个表【拆分后所有表的id一样,采用策略一样】
- 水平分片【垂直拆分】
- 水平分库:例如:将订单数据存放在多个数据库中
- 水平分表:将一张表的数据存放在多个订单表中
阿里巴巴Java开发手册:
【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。
说明:如果预计三年后的数据量根本达不到这个级别,`请不要在创建表时就分库分表`。
③读写分离和数据分片架构
架构演变过程
1.2 实现方式
- 程序代码封装
在代码中实现读写分离和数据库连接管理
- 中间件封装
独立一套系统出来,实现读写分离和数据库服务连接的管理。
- 常用解决方案
- Apache ShardingSphere(程序级别和中间件级别)
- MyCat(数据库中间件)
1.3 主从同步原理
slave会从master读取
binlog
来进行数据同步
具体步骤:
- master将数据改变记录到二进制日志(binlog)中
- 当slave执行start slave之后,slave会创建一个IO线程用来连接master,请求master中的binlog
- 当slave连接master之后,master会创建一个log dump线程,用于发送binlog的内容。在读取binlog的内容时候,会对主节点上的binlog进行加锁,当读取完成并发送给slave服务器后解锁
- IO线程接收主节点binlog dump进程发来的更新之后,会保存到中继日志(relay log)中
- 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 测试主从同步
- 添加实体类与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> {
}
- 测试类
@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.youkuaiyun.com/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)
);
③程序实现
- 修改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;
}
- 配置文件
#========================基本配置
# 应用名称
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取模算法
- 测试类
/**
* 水平分片:分库分表插入数据测试
* [根据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】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/
- 修改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;
}
- 在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=
- 测试
@Test
public void testKeyGenerator(){
Order order = new Order();
order.setUserId(1L);
order.setAmount(new BigDecimal(50));
order.setOrderNo("ZI412341");
orderMapper.insert(order);
}
- 结果
3 Sharding-Proxy
中间件封装
, 使用任意语言