为什么要分库分表?
单库表无论是存储还是cpu/网络等物理资源存在极限,对于日益增长的业务无法支撑
分库分表设计
默认按照主键作为分库分表的key
hash散列分库分表
优劣
优点:hash散列分布均匀,负载较为均衡
缺点:扩容难
扩容问题
- 扩容需要数据rehash+数据迁移,当然可以选择业务低峰时逐个迁移做到业务无感,但是迁移的成本与数据量成正比
- 可以学习参考HashMap的方案,扩容时避免rehash并且减少了迁移量,但是实用吗?为了成本当然时一台台扩容更为理想,不能每次扩容都成倍增长,该方案不适用当前场景
- 增量迁移?客户端兼容两套分库规则,在新规则未命中时迁移尝试迁移增量数据,风险高(DB层流量会被放大3倍阔不阔怕),业务代码侵入性强。可行但是风险成本都很高。虽可用但不可行。可以作为反面教材哈哈
- 原本一次查询被放大为:查新分库未命中,查旧分库命中,写新库
- 原本一次写入被放大为:查新分库未命中,查旧分库命中,merge新老数据后写新库
范围(按组)分库分表
优劣
优点:扩容容易,按需逐个扩容,比如:扩容3W-4W之间的主键,只需要配置下DB与分库规则即可,不需要rehash与迁移数据
缺点:热点问题,假如所有的数据均打在了某一个范围内,导致退化为单库问题。负载可能存在不均衡风险
热点问题
每日300W左右的数据增量,8个分库如何设计?
- 基于顺序主键
- 每个库37W?为了负载均衡需要配置多少个规则?规则的数量让你可能极其头疼,因为一天对应一个规则,并且会拖慢负责分库规则计算的客户端。
- 每个库扩大100倍3700W?何时扩容?需要计算下每个库表的负载能力,计算完之后按照负载能力定制分库规则。
- 主键不连续如何定制分库分表规则?例如:分布式主键。你不得不增加一个顺序的分库分表key,并且要维护分布式主键与顺序的分库分表key的映射,最严重的问题是:引入了新的分库分表问题,顺序key切分至分布式主键服务各个服务器上的“分库”问题。负载均衡也同样是一个极大的挑战,你不得不维护分布式主键与顺序分库分表key的映射关系。映射关系的维护,不得不考虑并发问题,增加并发锁会降低分布式主键的并发性能,不增加并发锁则需要维护线程与顺序key分片的轮询index下标。这仅仅解决了分布式主键与顺序key映射,基于顺序key再进行分库分表规则路由数据。该方案的复杂度可想而知
各种定制逻辑,如果业务量快速增长,每日600W左右的数据增量,原定制化逻辑是否均需要随之调整?
- 顺序key新增范围与分布式主键服务器映射规则维护
- 顺序key新增范围与DB映射规则维护
热点问题如果想要解决付出的成本过高,回过头了大家会发现,其实更佳的解决方案已经被我们发现了,因为两种分库分表的设计方案的优劣完全互补,没错,整合两种方案就是我们锁需要的分库分表设计方案
hash散列+范围(按组)分库分表
整合后的设计方案不再额外画图,关于整合其实也有两种选择
- 先hash再范围
- 先范围再hash
先hash再范围
- 无热点问题,与hash函数选择相关,hash函数只要别太无脑过分,不会存在热点问题
- 扩容:基于范围进行DB扩容,不影响老数据,仅影响最后一个兜底范围,需要进行部分数据的迁移,甚至不需要迁移,如果最后一个兜底范围的上限制在新扩展范围区间内
有没有联想到另一个概念?反正我是有的,这像极了一致性hash,一致性hash也是解决动态扩容的常用方案
按照3700W为一个范围对应两个分库单表设计,最差情况单库支撑3700W(hash冲突极端场景),8个分库可以支撑1.48亿数据,每日增量300W可以支撑400天,也就是一年多,陈旧数据可以迁移至历史库,足以支撑大量业务
先范围再hash
- 无扩容问题,当数据即将到达某个范围区间时将新的DB扩容上去即可
- 热点问题,单个范围内通过hash散列至各个DB
设计方案以及支撑业务能力同“先hash再范围”相同,针对后hash散列,不能仅使用两个分库单表设计,而是两个分库+8个分表设计,尽量打散热点数据
总结
- 线上实际分库分表规则为8个分库单表设计,每日200-300W增量数据,日常库保留3天,3天外数据将迁移至历史库,大促峰值日增860W左右,峰值持续3天,单库峰值220W左右,分库的key选用业务单据的城市ID,自定义分库规则,缺点是比较死板。当然除非热点城市业务量快速迁移至另一个热点城市导致热点合并,单库表压力扛不住,正常情况下不会有问题。而且至今也没有遇到该场景,毕竟城市业务就像城市发展,三线城市发展为二线城市,二线城市发展为一线城市,一线城市的库表数据能扛住,二三线城市也能扛住,而且城市的发展并不想文字说变就变,需要比较长的时间。优点是规则极其简单,几乎不需要分库规则维护。而且也经历了线上验证,不得不说是一个很好的设计^_^!
- 不论是哪种方案,根据实际的业务场景选择适合自己的就是最好了,哪怕单库单表,只要业务量级允许,那就是最好的选择