什么时候才需要分库分表
MySQL单表数据量到千万级、单库连接并发到极限、单表索引与缓存失效严重,这时候才考虑分库分表。分库分表方案不是想上就上,它会改变SQL写法、事务边界和查询方式,属于数据库架构级改动,数据量没到千万级时先做读写分离和索引优化,是性价比更高的选择。需要分的时候,优先推荐ShardingSphere-JDBC这类无侵入的Java中间件,它嵌入应用内,无需额外部署。
ShardingSphere-JDBC接入与配置
引入依赖后在application.yml里配置数据源和分片规则:
spring:
shardingsphere:
datasource:
names: ds0, ds1
ds0:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://10.0.0.1:3306/order_db0
username: root
password: xxxx
ds1:
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://10.0.0.2:3306/order_db1
username: root
password: xxxx
rules:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..1}.t_order_$->{0..1}
table-strategy:
standard:
sharding-column: order_id
sharding-algorithm-name: order_id_mod
key-generate-strategy:
column: id
key-generator-name: snowflake
sharding-algorithms:
order_id_mod:
type: MOD
props:
sharding-count: 4
key-generators:
snowflake:
type: SNOWFLAKE
核心逻辑是:order_id取模4决定数据落在哪个物理分片(2库×2表),ID由雪花算法全局生成,业务代码不用改任何SQL,中间件在数据源层自动路由。
分片算法选型:取模、哈希与时间分片
分片算法直接决定数据分布和查询效率,三种主流:
取模/哈希分片:按主键哈希取模,数据均匀分布,但扩容时要重新分片(从4片扩到8片需要迁移全部数据)。
范围分片(order_id在某个区间落在某库):扩容简单,加节点迁移少,但热门区间数据集中,容易成为热点。
时间分片:按月份建表(order_202608),适合日志、流水类数据,历史库自动归档,查询必须带时间范围条件。
选择原则:查询经常带条件字段选等值(用户id、订单id),分片键尽量选等值查询最多的字段,不带分片键的查询会全路由扫描,业务要尽量避免。
分布式ID与全局唯一键
分库分表后数据库自增主键失效,需要全局唯一ID。首选雪花算法(Snowflake):64位=时间戳+机器ID+序列号,单调递增且无需中心服务,生成顺序性对MySQL索引页友好。ShardingSphere内置雪花生成器,生产上也可以自建中心化发号器。全局ID必须在写入前生成,业务代码里不能用数据库回填。
存量数据迁移与线上验证
存量迁移是分库分表最难的一环,标准步骤:先对源库做数据一致性快照校验(校验行数+校验和),再通过双写(新老库同时写入)期间增量同步,最后切换读流量并监控告警。观察指标:业务写成功率、主从延迟、慢SQL数量,稳定运行48小时再拆掉双写。
迁移期间避免一次性全量灌数据,按主键分批,分批大小控制在5000-10000条,每批后检查延迟。分库分表做完后,跨分片的聚合查询(如分页、排序)要引入中间件层合并或改为数据仓方案,这一点决定了系统的最终复杂度边界。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/mysql-fen-ku-fen-biao-fang-an-shi-zhan-shardingspherejdbc/