可昕之家

可昕之家

张先生

平淡如水,爱护家人,好好工作

57 文章数
0 评论数

ComplexKeysShardingAlgorithm 详解

张清磊
2025-04-21 / 0 评论 / 36 阅读 / 0 点赞

ComplexKeysShardingAlgorithm 详解

ComplexKeysShardingAlgorithm 是 Apache ShardingSphere 中的一种分片算法实现,用于处理基于多个分片键的复合分片场景

一、基本概念

1. 核心作用

ComplexKeysShardingAlgorithm 允许您:

  • 同时使用多个列作为分片键(复合分片键)
  • 对这些分片键值进行组合计算,最终确定数据应该路由到哪个分片

2. 典型应用场景

  • 需要根据用户ID+订单时间进行分片
  • 需要根据地区+业务类型进行分片
  • 其他需要多条件组合决定数据分布的复杂分片场景

二、实现原理

1. 算法接口

public interface ComplexKeysShardingAlgorithm<T extends Comparable<?>> extends ShardingAlgorithm {
    Collection<String> doSharding(Collection<String> availableTargetNames, 
                                 ComplexKeysShardingValue<T> shardingValue);
}

public interface ComplexKeysShardingAlgorithm<T extends Comparable<?>> extends ShardingAlgorithm {
Collection<String> doSharding(Collection<String> availableTargetNames,
ComplexKeysShardingValue<T> shardingValue);
}


2. 核心参数

  • availableTargetNames:所有可选的分片目标(如表名或数据源名)
  • shardingValue:包含多个分片键及其值的容器对象

3. ComplexKeysShardingValue 结构

public final class ComplexKeysShardingValue<T extends Comparable<?>> {
    private final String logicTableName;
    private final Map<String, Collection<T>> columnNameAndShardingValuesMap;
    private final Map<String, Range<T>> columnNameAndRangeValuesMap;
}

public final class ComplexKeysShardingValue<T extends Comparable<?>> {
private final String logicTableName;
private final Map<String, Collection<T>> columnNameAndShardingValuesMap;
private final Map<String, Range<T>> columnNameAndRangeValuesMap;
}


三、配置示例

YAML 配置示例

rules:
- !SHARDING
  tables:
    t_order:
      actualDataNodes: ds_${0..1}.t_order_${0..15}
      tableStrategy:
        complex:
          shardingColumns: user_id,order_date
          algorithmClassName: com.example.MyComplexKeysShardingAlgorithm

rules:

- !SHARDING
  tables:
  t_order:
  actualDataNodes: ds_$​{0..1}.t_order_${0..15}
  tableStrategy:
  complex:
  shardingColumns: user_id,order_date
  algorithmClassName: com.example.MyComplexKeysShardingAlgorithm


Java 实现示例

public class MyComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
  
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, 
                                       ComplexKeysShardingValue<Long> shardingValue) {
      
        // 获取分片键值
        Map<String, Collection<Long>> columnValues = shardingValue.getColumnNameAndShardingValuesMap();
        Collection<Long> userIds = columnValues.get("user_id");
        Collection<Long> orderDates = columnValues.get("order_date");
      
        // 自定义分片逻辑
        Long userId = userIds.iterator().next();
        Long orderDate = orderDates.iterator().next();
      
        // 示例:user_id后两位+年月取模
        int suffix = (int)(userId % 100);
        int monthValue = LocalDateTime.ofInstant(
            Instant.ofEpochMilli(orderDate), ZoneId.systemDefault())
            .getMonthValue();
      
        int index = (suffix + monthValue) % availableTargetNames.size();
      
        return Collections.singletonList("t_order_" + index);
    }
}

四、与其它分片算法对比

算法类型 分片键数量 适用场景 特点
ComplexKeysShardingAlgorithm 多分片键 需要多个字段组合分片 灵活度高,逻辑可自定义
StandardShardingAlgorithm 单分片键 简单分片场景 实现简单,性能好
HintShardingAlgorithm 无固定分片键 强制路由场景 通过Hint指定分片

五、最佳实践建议

  1. 分片键选择原则
    • 选择高基数列(区分度高)
    • 选择经常出现在查询条件中的列
    • 避免选择频繁更新的列
  2. 分片算法设计
    • 确保数据分布均匀
    • 考虑未来扩容需求(如使用一致性哈希)
    • 避免跨分片查询(尽量让相关数据在同一分片)
  3. 性能考虑
    • 分片逻辑尽量简单高效
    • 避免在分片算法中执行复杂计算
    • 考虑使用预计算的分片键值
  4. 事务考虑
    • 多分片键可能导致分布式事务
    • 设计时考虑尽量减少跨分片操作

ComplexKeysShardingAlgorithm 提供了极大的灵活性,特别适合需要根据多个业务维度进行数据分片的复杂场景。正确使用可以显著提升分布式数据库系统的性能和可扩展性。

上一篇 下一篇
评论
最新回复
    暂无内容
光阴似箭
今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月
文章目录
今日天气