★ 分库分表怎么做?水平/垂直、取模/一致性哈希怎么选,代价是什么?

结论先行:分库分表是应对单库容量与写入吞吐上限的最后手段,核心是选好切分维度与路由算法。垂直拆分先做(按业务/字段拆),水平拆分后做(按行拆);路由常用取模与一致性哈希,各有扩容与热点的取舍;同时要清醒认识到它会带来跨库 join、分布式事务、分布式 id、排序分页等新问题。

一、先拆什么:垂直 vs 水平

维度垂直拆分水平拆分
拆法按业务模块/按列拆按行拆到多个库表
例子订单库与用户库分开;大字段拆出user_0 ~ user_15
解决字段多、模块耦合、单库连接数单表数据量、单库写入吞吐
局限不解决单表行数膨胀非路由键查询不友好

二、路由算法怎么选

算法规则优点缺点
范围分片按 id/时间区间易扩容、利于范围查询热点集中在新区间
取模id % N 定库表均匀、实现简单扩容需迁移重分布
一致性哈希环形空间 + 虚拟节点增减节点只影响少量数据实现复杂、可能不均
取模:     表号 = shard_key % 16
一致性哈希:shard_key 哈希后落到环上最近节点,虚拟节点摊平倾斜

三、必须提前想好的新问题

  • 跨库 join 与跨库事务:需要应用层聚合或引入分布式事务方案。
  • 分布式 id:不能依赖自增,常用雪花算法或号段模式。
  • 全局排序分页:LIMIT 需各分片取回后内存归并,深分页代价大。
  • 扩容迁移:取模扩容要双写 + 迁移工具,或翻倍扩容(2N)降低复杂度。
  • 热点数据:爆款行仍会集中到一个分片,需在其上叠加缓存/缓冲。
  • 全局唯一性:订单号、流水号等业务键要全局唯一设计,不能依赖分片内自增。

常见追问与记忆点

  • 追问:什么量级该考虑分库分表?没有铁律,单表几千万行或单库写入成瓶颈且索引/缓存已到位时再评估。
  • 追问:分片键选错了怎么办?只能选最核心的查询维度(订单号、用户 id),其它维度靠映射表/冗余/ES 兜底。
  • 追问:分库后分布式 id 怎么生成?雪花算法或号段模式二选一,要求全局唯一且尽量趋势递增。
  • 追问:先分库还是先分表?先分库解决连接与吞吐,再分表解决单表数据量,设计时一步到位减少二次迁移。
  • 记忆点:垂直先拆字段与模块,水平再拆行;取模均匀难扩容、一致性哈希易扩容有倾斜风险;买的是容量,付的是复杂度。
笔记加载中…