分库分表实战及中间件(四)
分库分表实战及中间件(四)
在一些应用场景中,分片条件并不存在于SQL,而存在于外部业务逻辑。因此需要提供一种通过在外部业务代码中指定路由配置的一种方式,在ShardingSphere中叫做Hint。如果使用Hint指定了强制分片路由,那么SQL将会无视原有的分片逻辑,直接路由至指定的数据节点操作。
Hint使用场景
- 数据分片操作,如果分片键没有在SQL或数据表中,而是在业务逻辑代码中
- 读写分离操作,如果强制在主库进行某些数据操作
在读写分离结构中,为了避免主从同步数据延迟及时获取刚添加或更新的数据,可以采用强制路由走主库查询实时数据,使用hintManager.setMasterRouteOnly设置主库路由即可。
如何使用
就想我们之前自定义分表策略一样,sharding也为我们提供了接口,实现HintShardingAlgorithm接口,编写分库或分表路由策略。
这儿我们配置test0,test1两个数据库,两个库中分别分了两个表position_master_slave0,position_master_slave1
我们对其取模2进行强制路由策略
/**
* hint 分片策略
*/
public class HintStrategyConfig implements HintShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(
Collection<String> collection, //库或者表集合
HintShardingValue<Long> hintShardingValue//路由key
) {
List<String> result = new ArrayList<>();
for (String table : collection) {
Collection<Long> values = hintShardingValue.getValues();
for (Long value : values) {
//这儿指定路由规则 我们这儿对库取模 后缀是多少进行选择库
if (table.endsWith(String.valueOf(value % 2))){
result.add(table);
}
}
}
return result;
}
}
配置
#打印shardingsphere sql
spring.shardingsphere.props.sql.show=true
# 分库信息配置
spring.shardingsphere.datasource.names=test0,test1
#配置数据库信息
#配置连接池
spring.shardingsphere.datasource.test0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.test0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.test0.jdbc-url=jdbc:mysql://localhost:3306/test0
spring.shardingsphere.datasource.test0.username=root
spring.shardingsphere.datasource.test0.password=root
#配置连接池
spring.shardingsphere.datasource.test1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.test1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.test1.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.shardingsphere.datasource.test1.username=root
spring.shardingsphere.datasource.test1.password=root
#hint 强制指定库 路由
#强制路由库和表
## 指定库路由
spring.shardingsphere.sharding.tables.position_master_slave.database-strategy.hint.algorithm-class-name=com.udeam.hint.HintStrategyConfig
## 指定表路由
spring.shardingsphere.sharding.tables.position_master_slave.table-strategy.hint.algorithm-class-name=com.udeam.hint.HintStrategyConfig
spring.shardingsphere.sharding.tables.position_master_slave.actual-data-nodes=test$->{0..1}.position_master_slave$->{0..1}
# 表 雪花算法id
spring.shardingsphere.sharding.tables.position_master_slave.key-generator.column=id
#对应主键类getType返回内容
spring.shardingsphere.sharding.tables.position_master_slave.key-generator.type=SNOWFLAKE
这儿准备好了响应的库和表
强制路由库
HintManager hintManager = HintManager.getInstance();
//选择库的路由 主库进行 0在我们自定义的路由算法中 对 两个库(test0,test1) % 2 操作 就是选择第一个库 即主库test0
hintManager.setDatabaseShardingValue(0L); // 强制路由库
System.out.println("记录数: " + positionMasterSlaveRepository.findAll().size());
可以看到test0中的所有表都进行查询
对某个库中表进行路由
@org.junit.Test
public void hintTest() {
/**
* 2 对某个库中表进行路由
*/
HintManager hintManagerTable = HintManager.getInstance();
//指定库
hintManagerTable.addDatabaseShardingValue("position_master_slave",0L);
//选择库中某个表进行路由,这儿设置对主库中 position_master_slave 表查询
hintManagerTable.addTableShardingValue("position_master_slave",0L);
System.out.println("记录数: " + positionMasterSlaveRepository.findAll().size());
}
如果不指定则会全部库和表都撸一遍
HintManager hintManagerTable = HintManager.getInstance();
System.out.println("记录数: " + positionMasterSlaveRepository.findAll().size());
源码分析
待写…
转载自:https://juejin.cn/post/7231803423577473082