知识卡片
分区再平衡策略从反面教材hash mod N到固定分区与动态分区
内容
节点增减时需要把负载从一些节点挪到另一些节点,这个过程叫再平衡,理想的再平衡要
满足:平衡后负载在节点间公平分配、平衡过程中数据库继续可读写、只搬运真正必须搬运
的数据(减少网络和磁盘I/O)。反面教材是用哈希值对节点数取模(hash(key) mod N):
这看起来是给键分配节点最直接的办法,但一旦N变化(加减节点),几乎所有键的
hash(key) mod N结果都会跟着变,导致绝大多数键要重新搬家,再平衡代价极高,这个
方案应被排除。可用的策略之一是固定数量的分区:一开始就创建远多于节点数的分区(比如
10节点集群从一开始切成1000个分区,每节点约100个),加节点时新节点从现有节点各”偷”
一些分区过来,分区数量和键到分区的映射规则都不变,只是分区所在的节点变了;这种
方案下分区数一旦定好通常不再改变,因此一开始要预留足够未来增长的空间,但分区太多
又有管理开销,且数据总量差异极大时很难选出”恰到好处”的分区数(Riak、Elasticsearch、
Couchbase、Voldemort用这种方式)。动态分区:分区大小超过阈值(如HBase默认10GB)时
自动一分为二,数据被大量删除、分区缩到某个下限以下时和相邻分区合并,这个过程和B树
分裂合并页面很像,优点是分区数量随数据总量自动伸缩,缺点是空数据库天生只有一个
分区、所有初始写入都压在这一个分区上,需要预分割来缓解。按节点比例分区(Cassandra
用):让分区数正比于节点数(每节点固定数量分区,如默认256个),新节点加入时随机
挑现有分区拆一半过来,分区大小随数据总量增长,但整体上因节点数增长而保持稳定,
本质上最贴近一致性哈希的原始定义。
结构图:
flowchart TD
A[hash mod N: 反面教材] -->|N变化几乎全部键都要搬家| A1[排除]
B[固定数量分区] --> B1[分区数不随节点数变, 新节点偷分区]
B1 -.分区数一旦定好难改, 需预估未来增长.-> B1
C[动态分区: 超阈值分裂/低于阈值合并] --> C1[分区数随数据量自动伸缩]
C1 -.空库只有一个初始分区, 需预分割.-> C1
D[按节点比例分区: 每节点固定分区数] --> D1[新节点随机拆现有分区]
D1 -.分区大小随数据量增长, 但整体因节点数增长而稳定.-> D1
参考来源
- 位置:《数据密集型应用系统设计》第六章《分区》"再平衡策略"(源文件:
_epub-src/ch6_split_005.html)
- 结论依据:原文说明hash mod N会导致节点数变化时几乎所有键都要重新分配因而是反面
教材,固定数量分区让新节点从现有节点偷分区、分区数不变,动态分区按大小阈值分裂
合并、需要预分割解决空库热点,按节点比例分区让分区数正比于节点数,直接支撑
本卡片的三种可用策略结构梳理。
- 原始内容:模N方法的问题是,如果节点数量N发生变化,大多数键将需要从一个节点
移动到另一个节点……创建比节点更多的分区,并为每个节点分配多个分区……当分区
增长到超过配置的大小时……会被分成两个分区……每个节点具有固定数量的分区。