SpringBoot sharding 分库分表使用及配置
官方提供配置方式有哪些?
JAVA配置
YAML配置
SpringBoot配置
Spring命名空间配置
无论哪种方式最后底层都包装成JAVA代码方式配置,今天主要以SpringBoot-sharding自动状态开始玩!

了解分库分表策略场景
StandardShardingStrategy 标准分片
1.只支持单个字段进行分片分库,自定义必须实现PreciseShardingAlgorithm 处理 = 和in分片,RangeShardingAlgorithm非必需,遇到BETWEEN AND分片如果不配置,会全表路由
ComplexShardingStrategy 复合分片 支持多分片
1.需要实现ComplexKeysShardingAlgorithm接口,支持in、=、和BETWEEN AND场景
InlineShardingStrategy 表达式分片 只支持单片
1.Inline表达式分片策略。使用Groovy的Inline表达式
HintShardingStrategy Hint分片
1.需要实现HintShardingAlgorithm接口自定义逻辑分片
NoneShardingStrategy 不分片
配置数据源
1.数据源Mysql配置主从同步,所以配置时加了读写分离数据源配置。
spring:
application:
name: sharding-mysql
shardingsphere:
datasource: # 数据源配置
## 数据库逻辑名称声明
names: u0,u1,u0-slave,u1-slave
u0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver # mysql8 com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://0.0.0.0:3306/demo0?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: backup
password: backup
u0-slave:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://0.0.0.0:3307/demo0?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
u1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://0.0.0.0:3306/demo1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: backup
password: backup
u1-slave:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver # mysql8 com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://0.0.0.0:3307/demo1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root

配置读写分离 (项目不需要可忽略)
⚠️注意:数据库逻辑名称 ds_u* 在后面配置分库分表的时候需要使用,分库分表会找到这个读写分离数据源名称下的主数据库数据源名称 和 从数据库 数据源名称 上述配置数据源。如果不需要读写分离 分库分表直接写 配置数据源名称。
# 读写分离
master-slave-rules:
ds_u0: # 读写分离数据源名称
masterDataSourceName: u0 #主数据库数据源名称
slaveDataSourceNames:
– u0-slave #从数据库 数据源名称
loadBalanceAlgorithmType: ROUND_ROBIN
ds_u1:
masterDataSourceName: u1
slaveDataSourceNames:
– u1-slave
loadBalanceAlgorithmType: ROUND_ROBIN

分库配置
## 分库策略配置
sharding:
## 默认分库策略 支持3种 standard:用于单分片键的标准分片场景 \ complex:用于多分片键的复合分片场景 \ inline:行表达式分片策略 \ hint:Hint分片策略 none:不分片 只能选择一种 同时分表策略一样可以使用
default-database-strategy:
inline:
sharding-column: tenant_id #分库键
algorithm-expression: ds_u$->{tenant_id % 2} # 分库键 % 2 余数 == master?当出现读写分离使用ds_u$ 没有读写分离 则u$ (u0)

分表配置
1.下面2张表 user 和order
2.type: SNOWFLAKE ID生成器 只支持单个数据insert 不支持批量。批量会导致分表数据错路(偶数表存奇数数据,奇数表存偶数数据),如果批量insert自行生成雪花ID 注释配置。
## 分表策略
tables:
user: ## 逻辑表名称
actual-data-nodes: ds_u$->{0..1}.user_$->{0..1} #由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式
# 最好别使用框架自带 主键生成 容易导致 0表ID为奇数 1表ID为偶数 数据相反 针对项目批量insert问题 单个insert可以使用这个
key-generator:
column: id #自增列名称,缺省表示不使用自增主键生成器
type: SNOWFLAKE #自增列值生成器类型 SNOWFLAKE\UUID
table-strategy:
inline:
sharding-column: id # 分片列名
algorithm-expression: user_$->{id % 2} #id %2 余数选择表 user_0\user_1
oder:
actual-data-nodes: ds_u$->{0..1}.oder_$->{0..1}_$->{0..1}
table-strategy:
complex:
sharding-columns: order_id,user_id
algorithm-class-name: com.example.shardingmysql.config.MyComplexShardingAlgorithm

3.MyComplexShardingAlgorithm 使用自定义分表策略
/**
* 符合组件分表策略
*
* @Author MostSnails
* @Version 1.0
*/
@Slf4j
public class MyComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm {

@Override
public Collection<String> doSharding(Collection collection, ComplexKeysShardingValue complexKeysShardingValue) {
log.info(“collection:{},complexKeysShardingValue:{}”, JSON.toJSONString(collection), JSON.toJSONString(complexKeysShardingValue));
List<String> result = new ArrayList<>();

//获取分表列 分片表规则order_(orderId%2)_(userId%2)
Collection<Long> order_id = this.getShardingValue(complexKeysShardingValue, “order_id”);
Collection<Long> user_id = this.getShardingValue(complexKeysShardingValue, “user_id”);
//查询SQL 一个分片键都没有情况
if (user_id.isEmpty() && order_id.isEmpty()) {
collection.forEach(table -> {
result.add(String.valueOf(table));
});
return result;
}
//查询SQL 只有orderId 一个分片建
if (user_id.isEmpty()) {
for (Long orde : order_id) {
String tmpTableName = orde % 2 + “_0”;
String tmpTableName1 = orde % 2 + “_1”;
collection.forEach(table -> {
if (String.valueOf(table).endsWith(tmpTableName) || String.valueOf(table).endsWith(tmpTableName1)) {
result.add(String.valueOf(table));
}
});

}
return result;
}
//查询SQL 只有user_id 一个分片建
if (order_id.isEmpty()) {
for (Long user : user_id) {
String tmpTableName = “order_0_” + user % 2;
String tmpTableName1 = “order_1_” + user % 2;
result.add(tmpTableName);
result.add(tmpTableName1);
}
return result;
}
//全部都有分片键存在
for (Long user : user_id) {
for (Long orde : order_id) {
String tmpTableName = orde % 2 + “_” + user % 2;
collection.forEach(table -> {
if (String.valueOf(table).endsWith(tmpTableName)) {
result.add(String.valueOf(table));
}
});
}
}
return result;
}

//获取分片键的值
private Collection<Long> getShardingValue(ComplexKeysShardingValue complexKeysShardingValue, String key) {
Collection<Long> result = new ArrayList<>();
if (complexKeysShardingValue.getColumnNameAndShardingValuesMap().size() > 0 && complexKeysShardingValue.getColumnNameAndShardingValuesMap().containsKey(key)) {
Collection<Long> value = (Collection<Long>) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get(key);
for (Long v : value) {
result.add(v);
}
return result;
}
return result;
}
}

事务、强制路由
1.shardingjdbc实现xa分布式事务只需要加入依赖(也支持seata等),增加注解
@Sharding TransactionType = (value = TransactionType.XA)
@Transactional(rollbackFor = Exception.class)

2.主从复制有延迟 强制路由加入代码HintManager.getInstance().setMasterRouteOnly();
官方配置文档
传送门

整体YMAL配置
server:
port: 8082
spring:
application:
name: sharding-mysql
shardingsphere:
datasource: # 数据源配置
## 数据库逻辑名称声明
names: u0,u1,u0-slave,u1-slave
u0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver # mysql8 com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://0.0.0.0:3306/demo0?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: backup
password: backup
u0-slave:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://0.0.0.0:3307/demo0?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
u1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://0.0.0.0:3306/demo1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: backup
password: backup
u1-slave:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver # mysql8 com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://0.0.0.0:3307/demo1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root

## 分库策略配置
sharding:
## 默认分库策略 支持3种 standard:用于单分片键的标准分片场景 \ complex:用于多分片键的复合分片场景 \ inline:行表达式分片策略 \ hint:Hint分片策略 none:不分片 只能选择一种 同时分表策略一样可以使用
default-database-strategy:
inline:
sharding-column: tenant_id #分库键
algorithm-expression: ds_u$->{tenant_id % 2} # 分库键 % 2 余数 == master?当出现读写分离使用ds_u$ 没有读写分离 则u$ (u0)
## 分表策略
tables:
user: ## 逻辑表名称
actual-data-nodes: ds_u$->{0..1}.user_$->{0..1} #由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式
# 最好别使用框架自带 主键生成 容易导致 0表ID为奇数 1表ID为偶数 数据相反 针对项目批量insert问题 单个insert可以使用这个
key-generator:
column: id #自增列名称,缺省表示不使用自增主键生成器
type: SNOWFLAKE #自增列值生成器类型 SNOWFLAKE\UUID
table-strategy:
inline:
sharding-column: id # 分片列名
algorithm-expression: user_$->{id % 2} #id %2 余数选择表 user_0\user_1
oder:
actual-data-nodes: ds_u$->{0..1}.oder_$->{0..1}_$->{0..1}
table-strategy:
complex:
sharding-columns: order_id,user_id
algorithm-class-name: com.example.shardingmysql.config.MyComplexShardingAlgorithm

# 读写分离
master-slave-rules:
ds_u0: # 读写分离数据源名称
masterDataSourceName: u0 #主数据库数据源名称
slaveDataSourceNames:
– u0-slave #从数据库数据源名称
loadBalanceAlgorithmType: ROUND_ROBIN
ds_u1:
masterDataSourceName: u1
slaveDataSourceNames:
– u1-slave
loadBalanceAlgorithmType: ROUND_ROBIN

props:
sql:
show: true #打开SQL打印

mybatis:
mapper-locations: classpath:/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
type-aliases-package: com.example.shardingmysql.entity
mapper:
mappers: com.example.shardingmysql.base.TkMapper
identity: MYSQL
————————————————
版权声明:本文为CSDN博主「MostSnails」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/MostSnails/article/details/121320013