articleList

31-Sharding-Jdbc分片策略实战之Hint分片算法

2025/03/13 posted in  ShardingJDBC
Tags: 

  • Hint分片策略HintShardingStrategy

    • hint的中文意思:提示、暗示
    • 这种分片策略无需配置文件进行配置分片健,分片健值也不再从 SQL中解析,外部手动指定分片健或分片库,让 SQL在指定的分库、分表中执行
    • 通过Hint代码指定的方式而非SQL解析的方式分片的策略
    • Hint策略会绕过SQL解析的,对于这些比较复杂的需要分片的查询,Hint分片策略性能可能会更好
    • 可以指定sql去某个库某个表进行执行
  • 编码(自定义完算法只实现了一部分,需要在调用 SQL 前通过 HintManager 指定分库、分表信息)

    • 分库

public class CustomDBHintShardingAlgorithm implements HintShardingAlgorithm {
/**

  • @param dataSourceNames 数据源集合
  •                      在分库时值为所有分片库的集合 databaseNames
    
  •                      分表时为对应分片库中所有分片表的集合 tablesNames
    
  • @param hintShardingValue 分片属性,包括
  •                      logicTableName 为逻辑表,
    
  •                      columnName 分片健(字段),hit策略此处为空 ""
    
  •                      <p>
    
  •                      value 【之前】都是 从 SQL 中解析出的分片健的值,用于取模判断
    
  •                      HintShardingAlgorithm不再从SQL 解析中获取值,而是直接通过
    
  •                      hintManager.addTableShardingValue("product_order", 1)参数进行指定
    
  • @return
    */

@Override
public Collection doSharding(Collection dataSourceNames, HintShardingValue hitShardingValue) {

Collection result = new ArrayList<>();
for (String datasourceName : dataSourceNames) {

for (Long shardingValue : hitShardingValue.getValues()) {

String value = shardingValue % dataSourceNames.size() + "";

if (datasourceName.endsWith(value)) {
result.add(datasourceName);
}
}
}
return result;
}
}

- 分表
```java
public class CustomTableHintShardingAlgorithm implements HintShardingAlgorithm<Long> {
 /**
  * @param dataSourceNames   数据源集合
  *                          在分库时值为所有分片库的集合 databaseNames
  *                          分表时为对应分片库中所有分片表的集合 tablesNames
  * @param hintShardingValue 分片属性,包括
  *                          logicTableName 为逻辑表,
  *                          columnName 分片健(字段),hit策略此处为空 ""
  *                          <p>
  *                          value 【之前】都是 从 SQL 中解析出的分片健的值,用于取模判断
  *                          HintShardingAlgorithm不再从SQL 解析中获取值,而是直接通过
  *                          hintManager.addTableShardingValue("product_order", 1)参数进行指定
  * @return
  */

 @Override
 public Collection<String> doSharding(Collection<String> dataSourceNames, HintShardingValue<Long> hitShardingValue) {

     Collection<String> result = new ArrayList<>();
     for (String datasourceName : dataSourceNames) {

         for (Long shardingValue : hitShardingValue.getValues()) {

             String value = shardingValue % dataSourceNames.size() + "";

             if (datasourceName.endsWith(value)) {
                 result.add(datasourceName);
             }
         }
     }
     return result;
 }
}
  • 配置(配置多个数据源ds)
# Hint分片算法
spring.shardingsphere.sharding.tables.product_order.table-strategy.hint.algorithm-class-name=net.xdclass.strategy.CustomTableHintShardingAlgorithm
spring.shardingsphere.sharding.tables.product_order.database-strategy.hint.algorithm-class-name=net.xdclass.strategy.CustomDBHintShardingAlgorithm
  • 编码测试
    /**
     * 正常可以用AOP进行实现
     */
    @Test
    public void testHit() {

        //清除历史规则
        HintManager.clear();

        //获取对应的实例
        HintManager hintManager = HintManager.getInstance();

        //设置库的分片键值,value是用于库分片取模
        hintManager.addDatabaseShardingValue("product_order", 3L);

        //设置表的分片键值,value是用于表分片取模
        hintManager.addTableShardingValue("product_order", 8L);

        //如果在读写分离数据库中,Hint 可以强制读主库(主从复制存在一定延时,但在业务场景中,可能更需要保证数据的实时性)
        //hintManager.setMasterRouteOnly();

        //对应的value,只做查询,不做sql解析
        productOrderMapper.selectList(new QueryWrapper<ProductOrderDO>().eq("id", 66L));
    }