likes
comments
collection
share

Springboot3 shardingsphere 5.2.1 分库分表实践

作者站长头像
站长
· 阅读数 23

明月别枝惊鹊,清风半夜鸣蝉。

1 前言

在互联网和大数据时代,单一数据库难以满足高并发和海量数据的存储需求。Apache ShardingSphere 作为一个强大的分布式数据库中间件,提供了高效的分库分表功能,以应对日益复杂的存储挑战。本文将以 为基础添加分库分表业务,本文以 ShardingSphere 5.2.1 版本为实践案例,深入分析其使用中的注意事项。

2 项目准备

在前文中已经讲述了项目搭建的过程,对于 ShardingSphere 的引入,只需要在 pom 项目中引入 ShardingSphere 的依赖即可。以下是 maven 的依赖配置,这已经是最新的:

-- 依赖排除了 quartz 的引用,在 sharding-sphere-starter 中集成了很多模块,对于不需要的可以进行排除,这一点和 nacos-discovery 类似。
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.2.1</version>
    <exclusions>
        <exclusion>
            <artifactId>quartz</artifactId>
            <groupId>org.quartz-scheduler</groupId>
        </exclusion>
    </exclusions>
</dependency>

3 分库分表策略和算法

3.1 分库分表策略

在新版本中分库分表策略包含有标准分片策略、复合分片策略、Hin分片策略、不分片策略。分片策略就是分片键+分片算法。具体如下图所示,详见YamlShardingStrategyConfigurationSpringboot3 shardingsphere 5.2.1 分库分表实践

分片策略使用条件操作符
标准分片策略使用单一分片键的,支持精确分片。需要指定分片字段shardingColumn和分片算法名shardingAlgorithmName=、in 、between and、 >、 < 、>=、<=
复合分片策略适用于多个分片键的场景,分片字段shardingColumn使用逗号间隔支持条件和标准分片相同
强制分片策略无需配置分片键,由外部指定分库分表信息。使用场景:1 分片字段不再收据库结构而在外部业务,2 强制在指定数据库进行数据操作。-
不分片策略对逻辑表的所有操作都会在全库表进行路由操作。-
3.2 分库分表算法

ShardingSphere 5.2.1 中新增了许多分片字段,按照类型划分可以分为自动分片算法,标准分片算法,复合分片算法以及 Hint 分片算法,基本上覆盖到了大多数的业务场景。 这里需要说明一下,分库和分表的算法都是一样的,想要知道所有的分片算法,可以看 StandardShardingAlgorithm 的实现类即可。

Springboot3 shardingsphere 5.2.1 分库分表实践

分片算法配置说明算法说明
自动分片-MOD需要指定 sharding-count ,即分片数量取模是一种内置的简单分算法,表达式为 (分片键或者数据库实例) % sharding-count
自动分片-HASHMOD同样需要指定分片数量 sharding-count和简单取模算法类似,不过换成了 hash 值取模,如果hash 取模为负数,会取其绝对值
自动分片-VOLUME_RANGE需要指定分片键取值的上下限(range-lower, range-upper),以及每个分片的容量 sharding-volume, 超过容量边界后会报错基于分片容量的范围分片算法,将数据按照容量均分到数据库表中
自动分片-BOUNDARY_RANGE根据边界值进行分片,和容量算法不同,需要指定范围的分界 sharding-ranges=1000,2000,30000,40000,按照数据边界可以分为5个数据库表。根据边界值将数据分别放在对应的分表中。
自动分片-AUTO_INTERVAL自动时间分片算法,和基于容量分片算法类似,不过这里采用的分片键为时间。需要指定时间的上下限,(datetime-lower,datetime-upper), 对应的时间戳格式为 yyyy-MM-dd HH:mm:ss,以及对应的分片容纳时间,sharding-seconds, 单位为秒。按照时间的方式将数据路由到不同的数据库表中。
行表达式-INLINE适用于比较简单的分片场景,需要指定分片表达式 algorithm-expression,以及是否支持范围查询 allow-range-query-with-inline-sharding,默认为 false基于行表达式的分片算法,使用 groovy语言,能够直观的看出分片的计算逻辑,只能支持 = 和 in 的 sql 操作
行表达式-INTERVAL基于时间的分片,上面的时间分片算法都是以 _n 为后缀,这里可以使用表后缀为_yyyyMMdd的格式。指定分片键的时间格式 datetime-pattern,默认为yyyy-MM-dd HH:mm:ss,分片值的取值范围(datetime-lower,datetime-upper),需要和分片键的格式一致,分片表的后缀格式 sharding-suffix-pattern一般为 yyyyMM、yyyyMMdd格式,分片表的单位间隔 datetime-interval-unit 取值为 MONTHS、DAYS,需要和 datetime-interval-amount 配合使用。基于时间分表算法,可以直观的看出数据存储的时间范围。
复合分片-COMPLEX_INLINE适用于多个分片键场景,多个分片键需要使用逗号间隔, 这里比 INLINE多了一个分片列 sharding-columns和行表达式的原理类似,也是需要使用 groovy 语言指定分片算法。
HINT分片-HINT_INLINE强制路由分片算法,需要指定算法的表达式 algorithm-expression, 其中的分片值需要在代码中通过 HintApi 进行指定。是一种根据业务需要计算分片路由的算法,在特殊的业务场景下使用。

此外,还有基于散列算法 COSID(一款高性能的分布式ID生成器),其核心思想是通过散列算法和分片键值进行处理,可以保证数据存放的均匀性,避免数据倾斜和个别节点负载高的问题。有以下三种分片算法 COSID_MODCOSID_INTERVALCOSID_INTERVAL_SNOWFLAKE,所需要的配置只是多添加了一个 真实表的前缀 logic-name-prefix

4 分库分表配置

对于分库分表的配置,ShardingSphere 提供了两种 java api ��� yml 两种配置,这里采用的是配置文件的方式,由于分库分表的配置项很多,这里采用了 properties 的配置,个人觉得比 yml 容易理解。

在开始配置之前,需要先配置数据库连接信息,如下图所示:

Springboot3 shardingsphere 5.2.1 分库分表实践

现在有一个 tb_order 表,分片键为 user_id , 需要进行分库分表, 例如 tb_order_2024_01,需要按照年份分表,每个年份分为5个表,同时需要分布在两个数据库中。首先需要设置分库分表的后缀范围:

# 设置分库分表后缀范围
spring.shardingsphere.rules.sharding.tables.tb_order.actual-data-nodes=db${0..1}.tb_order_$->{2020..2030}_${(0..4).collect{t ->t.toString().padLeft(2,'0')}}

分库策略比较简单,按照 user_id 取模运算,配置如下所示:

# 分库的策略配置
spring.shardingsphere.rules.sharding.tables.tb_order.database-strategy.standard.sharding-column=user_id
spring.shardingsphere.rules.sharding.tables.tb_order.database-strategy.standard.sharding-algorithm-name=database_inline
# 采用行表达式的方式进行分库
spring.shardingsphere.rules.sharding.sharding-algorithms.database_inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.database_inline.props.algorithm-expression=db${user_id % 2}

分表的策略比较复杂,这里采用了自定义的分表策略,在配置中如下所示:

# 配置分表分片键
spring.shardingsphere.rules.sharding.tables.tb_order.table-strategy.standard.sharding-column=user_id
spring.shardingsphere.rules.sharding.tables.tb_order.table-strategy.standard.sharding-algorithm-name=table_inline
# 这里采用 snowflake 生成 tb_order 的主键
spring.shardingsphere.rules.sharding.tables.tb_order.key-generate-strategy.column=id
spring.shardingsphere.rules.sharding.tables.tb_order.key-generate-strategy.key-generator-name=alg_snowflake
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.props.worker-id=12
# 分表策略,这里采用的是自定义分表策略,需要继承 StandardShardingAlgorithm
spring.shardingsphere.rules.sharding.sharding-algorithms.table_inline.type=USER_SHARDING_STRATEGY
spring.shardingsphere.rules.sharding.sharding-algorithms.table_inline.props.number=5

在自定义分片算法时,需要在 resources 中配置其分片策略,同时需要采用编程的方式实现接口的方法,进行分片操作。 Springboot3 shardingsphere 5.2.1 分库分表实践

这里如果不区分年份的话,可以采用行表达式的方式来实现分表,如下所示:

# 行表达式的分表算法
spring.shardingsphere.rules.sharding.sharding-algorithms.table_inline.type=INLINE
# 由于采用的是 groovy 语言,可以很灵活的实现,user_id 对5取模后+1,得到的是 1-5 的数,
# 这里采用了格式化两位展示,十位数补零,如果有两位数的表,这样的表名看起来比较整齐。
spring.shardingsphere.rules.sharding.sharding-algorithms.table_inline.props.algorithm-expression=tb_order_${String.valueOf(user_id % 5 + 1).padLeft(2,'0')}

除了正常的分库分表之外,还可以设置不分库分表、以及广播表、或者是分库不分表(只需要设置分库规则即可)。

配置实际操作表和广播表

# 配置实际表
spring.shardingsphere.rules.sharding.tables.tb_account.actual-data-nodes=db1.tb_account
# 配置广播表
spring.shardingsphere.rules.sharding.broadcast-tables=tb_config

5 注意事项

  • 1 分片键选择

选择合适的分片键非常重要。分片键应为业务中频繁查询和过滤的字段,如订单系统中的 user_idorder_id。合理的分片键选择可以显著提升查询性能。

    1. 扩展性

在设计分库分表时,应考虑未来的扩展性。可以预留一些数据节点和表,以便在数据量增长时平滑扩展。例如,初始时可以设置更多的实际数据节点,并通过动态调整分片算法来实现扩展。

    1. 数据迁移

对于已有的大量数据,需要精心规划数据迁移策略。可以采用数据迁移工具或编写迁移脚本,将数据平滑地迁移到新的分片结构中,确保数据迁移过程中的一致性和完整性。

    1. 分布式事务

分库分表后,事务处理变得更加复杂。可以使用 ShardingSphere 提供的分布式事务管理器,如 XA 事务、BASE 事务,或者引入第三方分布式事务解决方案,如 Seata,以确保事务的一致性和可靠性。

    1. 性能监控

在分库分表环境中,性能监控尤为重要。通过监控系统的性能指标,及时发现和优化分片策略和数据库配置,保证系统的高可用性和稳定性。可以使用 PrometheusGrafana 等工具进行性能监控和告警。

    1. 数据均衡

确保数据在各个分片中的均衡分布,避免某些分片数据量过大而影响性能。可以定期进行数据重分布,保持数据的均衡性。例如,可以通过调整分片算法或者重新分配数据节点来实现数据均衡。

    1. SQL 限制

由于分库分表的限制,部分 SQL 特性可能不被支持,如跨库 Join 和复杂子查询。在使用 ShardingSphere 时,需注意规避这些限制,优化 SQL 语句。例如,可以通过分批查询和应用层 Join 的方式来实现跨库查询。

6 总结

ShardingSphere 5.2.1 版本作为一个功能强大的分布式数据库中间件,为解决海量数据和高并发请求提供了高效的分库分表解决方案。在实际应用中,通过合理配置和使用 ShardingSphere,可以显著提升系统的扩展性和性能。通过关注分片键选择、数据迁移、分布式事务和性能监控等关键环节,可以确保系统的稳定性和一致性,为企业应用保驾护航。本文中所涉及的代码已经上传至 gitee, 欢迎交流学习。项目地址 fortunecloud

转载自:https://juejin.cn/post/7393314542095237130
评论
请登录