shardingsphere读写分离+分表
用到的框架:mybatis-plus、druid、shardingsphere-jdbc-spring-boot-starter
- 依赖(gradle配置,maven对应去mvnrepository查询)
implementation 'com.alibaba:druid:1.2.8'
implementation('com.baomidou:mybatis-plus-boot-starter:3.4.3')
implementation 'org.postgresql:postgresql:42.3.3'
implementation 'org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:4.1.1'
implementation 'org.apache.shardingsphere:sharding-jdbc-spring-namespace:4.1.1'
- yml配置
spring:
shardingsphere:
# 是否打印sql
props:
sql.show: true
datasource:
# 库1 的配置
db1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/dd_test
username: postgres
password: 123456
# 库2 的配置
db1-slave0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5433/dd_test
username: postgres
password: 123456
names: db1,db1-slave0
sharding:
# 默认的库
default-data-source-name: db1
# 绑定的表 不配置也没找出啥问题
binding-tables: dd_order,order_sku
default-table-strategy:
none:
default-database-strategy:
none:
# 配置表的分片规则
tables:
# 指定某个表的分片配置
dd_order:
# 这个配置是告诉sharding有多少个库和多少个表
actual-data-nodes: ms.dd_order_$->{
1..7}
#分库策略
database-strategy:
none:
# 行表达式
# inline:
# # 配置表分片的字段
# sharding-column: ship_id
# # 配置表分片算法
# algorithm-expression: dd_order_$->{ship_id % 7 +1}
# 主键生成策略(如果是自动生成的,在插入数据的sql中就不要传id,null也不行,直接插入字段中就不要有主键的字段)
key-generator:
# 对应的数据库表的主键
column: id
# 生成方式, 雪花模式
type: SNOWFLAKE
# 配置表分片策略
table-strategy:
standard:
sharding-column: id
precise-algorithm-class-name: cn.venny.shardingsphere.CustomShardingPreciseAlgorithm
range-algorithm-class-name: cn.venny.shardingsphere.CustomShardingRangeAlgorithm
# 指定某个表的分片配置
order_sku:
# 这个配置是告诉sharding有多少个库和多少个表
actual-data-nodes: ms.order_sku_$->{
1..9}
#分库策略
database-strategy:
none:
# 主键生成策略(如果是自动生成的,在插入数据的sql中就不要传id,null也不行,直接插入字段中就不要有主键的字段)
key-generator:
# 对应的数据库表的主键
column: id
# 生成方式, 雪花模式
type: SNOWFLAKE
# 配置表分片策略
table-strategy:
standard:
sharding-column: id
precise-algorithm-class-name: cn.venny.shardingsphere.CustomShardingPreciseAlgorithm
range-algorithm-class-name: cn.venny.shardingsphere.CustomShardingRangeAlgorithm
masterSlaveRules:
ms:
name: ms
master-data-source-name: db1
slave-data-source-names: db1-slave0
load-balance-algorithm-type: ROUND_ROBIN
- 2个算法代码:
- 用到的工具类
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Vick C
* @version 1.0
* @date 2022/3/8 22:56
*/
public class PatternUtils {
private static final Pattern SHARDING_TABLE_RULE = Pattern.compile("\\d");
public static String parseNum(String string) {
if (string == null || string.length() < 1) {
return null;
}
Matcher matcher = SHARDING_TABLE_RULE.matcher(string);
StringBuilder sb = new StringBuilder();
while (matcher.find()) {
sb.append(matcher.group());
}
return sb.toString();
}
}
- 第一个算法
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
/**
* @author Vick C
* @version 1.0
* @date 2022/3/8 22:52
*/
public class CustomShardingPreciseAlgorithm implements PreciseShardingAlgorithm<String> {
/** dd_order分7张表 */
private static final int ORDER_TABLE_NUM = 7;
/** order_sku分9张表 */
private static final int ORDER_SKU_TABLE_NUM = 9;
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
String columnName = shardingValue.getColumnName();
if (!"id".equals(columnName)) {
return null;
}
// 自定义正则表达式
String s = PatternUtils.parseNum(shardingValue.getValue());
// 工具类用spring即可
if (StringUtils.isEmpty(s)) {
return null;
}
long num = Long.parseLong(s);
long remain = 1;
if (shardingValue.getLogicTableName().contains("order_sku")) {
remain = num % ORDER_SKU_TABLE_NUM + 1;
} else {
remain = num % ORDER_TABLE_NUM + 1;
}
for (String availableTargetName : availableTargetNames) {
if (availableTargetName.endsWith(String.valueOf(remain))) {
return availableTargetName;
}
}
return null;
}
}
- 第二个算法
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import java.util.Collection;
import java.util.List;
/**
* @author Vick C
* @version 1.0
* @date 2022/3/8 22:59
*/
public class CustomShardingRangeAlgorithm implements RangeShardingAlgorithm<String> {
/** dd_order分7张表 */
private static final int ORDER_TABLE_NUM = 7;
/** order_sku分9张表 */
private static final int ORDER_SKU_TABLE_NUM = 9;
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<String> shardingValue) {
String columnName = shardingValue.getColumnName();
if ("id".equals(columnName)) {
Range<String> valueRange = shardingValue.getValueRange();
String logicTableName = shardingValue.getLogicTableName();
String lowerTable = calcTableValue(logicTableName, valueRange.lowerEndpoint(), availableTargetNames);
String upperTable = calcTableValue(logicTableName, valueRange.upperEndpoint(), availableTargetNames);
if (lowerTable != null && upperTable != null) {
List<String> list = CollectionUtils.singleList(lowerTable);
list.add(upperTable);
return list;
}
}
return null;
}
private String calcTableValue(String logicTableName, String lowerEndpoint, Collection<String> availableTargetNames) {
String s = PatternUtils.parseNum(lowerEndpoint);
if (StringUtils.notEmpty(s)) {
long num = Long.parseLong(s);
long remain = 1;
if (logicTableName.contains("order_sku")) {
remain = num % ORDER_SKU_TABLE_NUM + 1;
} else {
remain = num % ORDER_TABLE_NUM + 1;
}
for (String availableTargetName : availableTargetNames) {
if (availableTargetName.endsWith(String.valueOf(remain))) {
return availableTargetName;
}
}
}
return null;
}
}
- 数据库建表
略…注意shardingsphere不会自动建表,所有的表都要手动建
- 测试(略…)
pg使用insert into … on conflict (字段名) do update set …成功插入不同表
使用mybaits save()方法一样可以插入不同表