数据库分库分表方案:ShardingSphere实战
当单表数据量超过5000万行或单库QPS超过5000时,就需要考虑分库分表了。ShardingSphere是Apache基金会的开源项目,提供了分库分表的完整解决方案。本文分享我们使用ShardingSphere-JDBC实施分表的实战经验。
分片策略选择
哈希取模:按分片键的hash值对表数量取模。优点是数据分布均匀,缺点是范围查询需要扫描所有分片。适合按用户ID分片。
范围分片:按分片键的范围分配到不同分片。如订单按月份分片,2024年1月的数据在shard_01。优点是范围查询高效,缺点是数据分布可能不均(热点月份数据多)。
时间+哈希混合:先按时间范围粗分,再按哈希细分。兼顾范围查询和数据均匀性。
ShardingSphere-JDBC配置
以订单表分16张表为例。在Spring Boot中引入shardingsphere-jdbc-core依赖,配置分片规则:逻辑表名orders,实际表名orders_00到orders_15,分片键user_id,分片算法取模。
配置完成后,应用层代码无需修改——ShardingSphere拦截SQL,自动路由到正确的分片,合并结果返回。对开发者来说几乎透明。
分布式ID
分表后不能使用自增ID(每个分片的ID会冲突)。我们使用Snowflake算法生成分布式ID:时间戳(41位)+ 机器ID(10位)+ 序列号(12位),生成全局唯一的64位long型ID。ShardingSphere内置了Snowflake Key生成器,配置worker-id即可。
跨分片查询
分表最大的挑战是跨分片查询。如果查询条件不包含分片键,就需要扫描所有分片然后合并结果(称为"广播路由"),性能很差。解决方案:
- 尽量让查询都带上分片键
- 对于必须按非分片键查询的场景,建立二级索引表(映射表)
- 使用Elasticsearch做异构索引,数据通过Canal同步到ES
扩缩容
分表数量一旦确定,后续扩容比较麻烦(需要数据重分布)。建议一开始就预留足够的分片数(如16或32),即使初期数据量不大。扩容时通过数据迁移工具逐步将数据从旧分片迁移到新分片。
