ComplexKeysShardingAlgorithm 小结

ComplexKeysShardingAlgorithm 是 Apache ShardingSphere 中的一种复合分片算法。它的核心作用是让你能基于多个业务字段(比如user_id + order_id),完全自定义数据如何分布到不同的数据库或表中-。因为它的高度定制性,你需要自己实现具体的分片逻辑-1

我把它的核心信息整理成了一个表格,方便你快速了解:

方面详细说明
核心接口ComplexKeysShardingAlgorithm<T extends Comparable<?>>-
配合策略ComplexShardingStrategy-
关键方法Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<T> shardingValue)-13
主要目标1. 基于多字段(如用户ID、区域、时间等)进行复合路由计算。
2. 解决单字段分片键无法满足的复杂业务分片需求。
典型应用多租户SaaS系统(tenant_id + user_id)、金融订单系统(user_id + order_id)、需按时间+地理维度分片的数据平台。

🎯 概念、作用与使用场景分析

当业务增长,数据量巨大时,常会用到“分库分表”。ComplexKeysShardingAlgorithm就是为了解决复杂分片需求而生的:

  • 提供最大灵活度:ShardingSphere不对多分片键的组合逻辑做任何预设,而是将原始的分片键值、操作符(=>等)都交给开发者,让开发者实现最贴合业务的分片逻辑--16

  • 支持复杂SQL操作:该算法能处理SQL中包含=><>=<=INBETWEEN AND等多种操作符的场景,非常全面-1-3

  • 核心应用场景:它非常适合多租户系统(分片键:tenant_iduser_id)、订单系统(分片键:user_idorder_id)以及对查询性能要求极高的复杂业务场景-。

⚖️ 优缺点解析

  • 优点

    • 极高的灵活性:可以结合regiontenant_iddate等任意维度组合,制定如“特定区域的订单去ds_shard_1”的复杂分片策略-1-3

    • 更强的查询性能:原生SQL路由能精准定位到物理节点,避免全库全表扫描-3

  • 缺点

    • 复杂度高:需精准理解业务数据分布并手动编码,相比标准分片算法(如INLINE)实现门槛更高-。

    • 全局性能影响:在分片键缺失时可能退化为全路由扫描,大量BETWEEN ANDIN查询会触发多表扫描,需注意算法效率-8-22

    • 维护成本较高:分片算法与业务深度绑定,未来规则调整或扩容时可能需改动算法代码。

💻 实战演示:基于用户ID与省份的复合分片

下面通过一个自定义复合分片的示例,帮你更好地理解其实现机制。

1. 核心依赖

在项目中引入核心依赖,注意建议使用较新且稳定的版本。

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version> <!-- 请根据项目实际情况选择合适版本 -->
</dependency>

-2

2. 完整算法实现

创建一个Java类,实现ComplexKeysShardingAlgorithm接口。

public class UserProvinceTableShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, 
                                          ComplexKeysShardingValue<Long> shardingValue) {
        // 1. 获取逻辑表名,例如:t_order
        String logicTableName = shardingValue.getLogicTableName();

        // 2. 获取分片键对应的值集合
        Map<String, Collection<Long>> columnValuesMap = shardingValue.getColumnNameAndShardingValuesMap();
        Collection<Long> userIds = columnValuesMap.get("user_id");
        Collection<Long> provinceIds = columnValuesMap.get("province_id");

        // 3. 待路由的表名集合
        Set<String> actualTableNames = new HashSet<>();

        // 4. 处理IN查询,可能包含多个user_id
        if (userIds != null && !userIds.isEmpty()) {
            for (Long userId : userIds) {
                // 利用多个字段值来计算,例如:根据用户ID%4和省份ID%2组合计算表后缀
                Long tableSuffix = (userId % 4) * 2 + (provinceIds != null ? provinceIds.iterator().next() % 2 : 0);
                String actualTableName = logicTableName + "_" + tableSuffix;
                if (availableTargetNames.contains(actualTableName)) {
                    actualTableNames.add(actualTableName);
                }
            }
        } else if (provinceIds != null && !provinceIds.isEmpty()) {
            // 处理只有省份ID的查询
            for (Long provinceId : provinceIds) {
                // ... 基于省份ID的路由逻辑,需要确保能覆盖所有可能的数据分布
            }
        }

        // 5. 返回目标物理表集合
        return actualTableNames;
    }
}

-13-4

3. 配置方式

application.propertiesapplication.yml中配置数据源、分片规则和自定义算法。

properties

# 数据源配置省略...

# 配置order_logic表的分片策略
spring.shardingsphere.sharding.tables.order_logic.actual-data-nodes=ds0.order_logic_$->{0..7}
# 配置分库策略(使用行表达式简单分库)
spring.shardingsphere.sharding.tables.order_logic.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.order_logic.database-strategy.inline.algorithm-expression=ds${user_id % 2}
# 配置分表策略(使用复合分片算法)
spring.shardingsphere.sharding.tables.order_logic.table-strategy.complex.sharding-columns=user_id,province_id
spring.shardingsphere.sharding.tables.order_logic.table-strategy.complex.algorithm-class-name=com.example.UserProvinceTableShardingAlgorithm

--

📌 实际应用场景示例

  • 多租户订单系统:以tenant_id(租户ID)和order_id(订单ID)联合分片,强制租户隔离并分散热点--8

  • 电商用户行为表:以user_idevent_date联合分片,用user_id保证数据关联性,用event_date管理时间范围查询-2

  • 物联网设备数据:以product_line(产品线)和device_id(设备ID)联合分片,优先确保高优先级业务的数据隔离,再在内部均衡分布。

🔍 工作原理详解

  • 入口与策略ComplexShardingStrategy(复合分片策略)是入口,它将多分片键值和操作符完整地传递给ComplexKeysShardingAlgorithm.doSharding(...)方法进行最终决策-16-25-4

  • SPI机制与版本差异:ShardingSphere通过SPI机制加载算法实现。注意版本差异:在4.x及更早版本,一个ComplexKeysShardingAlgorithm实现需同时处理精确、IN和范围查询;而从5.x开始,官方更推荐使用StandardShardingAlgorithm + RangeShardingAlgorithm的模式来实现复合分片功能--1

💡 最佳实践与注意事项

  1. 优先选择标准算法:若单分片键能解决问题,优先用StandardShardingAlgorithm,它更简单且性能更好-8-22

  2. 合理设置分片键:分片键应尽量包含在常用SQL的WHERE条件中,避免路由到所有分片。索引设计要与分片策略协同,避免SQL解析性能瓶颈-8

  3. 警惕版本兼容性:升级ShardingSphere时需重审算法实现,确保doSharding方法的参数和ComplexKeysShardingValue的结构匹配新版本。

  4. 处理跨库查询:尽量减少跨库关联查询,通过数据冗余或字段冗余规避。需权衡跨库性能与数据一致性。

💎 总结

简单总结,ComplexKeysShardingAlgorithm 为你提供了高度的灵活性,但同时也伴随着实现和运维上的复杂性。如果简单分片已够用,优先选择标准算法(如基于INLINE表达式);只有当业务必须使用多字段进行分片路由时,才应该使用复合分片算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值