为什么需要一致性哈希
把数据分到多个节点,最直接的做法是对键取模:节点数一变,几乎所有键的归属都会重算,缓存与副本要全量搬一遍。一致性哈希把节点和键都映射到一个环形地址空间,键顺时针找到的第一个节点就是归属,增减节点只影响环上一段区间,迁移量因此从「几乎全部」降到「约一节」。
基本信息
| 适用类型 | 分布式缓存、对象存储、分片数据库的分片算法 |
|---|---|
| 核心思想 | 键与节点同环映射,就近归属 |
| 常见改进 | 虚拟节点、权重、有界负载(bounded loads) |
| 典型实现 | 多数对象存储用的是受控复制算法而非裸环 |
典型使用场景
- 缓存集群扩缩容:希望扩容后大部分键仍落在原节点
- 对象存储分片:把对象按哈希分到存储节点并叠加故障域约束
- 分片数据库:需要可预测且迁移量可控的切片方式
- 负载评估:预估节点增减时的数据搬移比例与耗时
虚拟节点示意
虚拟节点示意
# 裸环的问题:节点少时,环上区间大小随机,负载不均
# 做法:每个物理节点映射成多个虚拟节点,分散到环上
digest = hash('node-A#0') -> 环上位置 1
digest = hash('node-A#1') -> 环上位置 2
# 物理节点权重越高,分配的虚拟节点越多,承接的数据越多三种分片方式对比
| 方式 | 节点变化时的影响 | 主要缺点 |
|---|---|---|
| 取模散列 | 几乎全部键重新归属 | 扩容等于一次全量搬迁 |
| 一致性哈希 | 仅相邻区间迁移,约一节比例 | 节点少时分布不均,需虚拟节点 |
| 受控复制 | 按故障域挑选副本集,带权重与负载约束 | 实现复杂,需要维护映射表 |
虚拟节点数量越多分布越均匀,但元数据与查找开销也越大;实践中常取每节点上百个虚拟节点作为折中。
一致性哈希解决的是「归属稳定」,不解决「副本放哪里」;跨机架、跨机房的高可用约束要靠上层放置规则表达。