什么是一致性哈希?为什么要引入虚拟节点?
简化版
一致性哈希是一种分布式映射算法,把节点和数据 key 都映射到同一个哈希环上,key 顺时针找到的第一个节点就是它的归属节点。相比普通取模,节点扩容或下线时只会影响环上相邻一小段数据,减少缓存失效和数据迁移。虚拟节点用于让数据分布更均匀,避免少量真实节点造成倾斜。
详细版
普通取模 hash(key) % N 的问题是 N 一变,大量 key 的结果都会变化。比如缓存从 3 台扩到 4 台,绝大多数 key 都会重新映射,导致缓存雪崩式失效。
一致性哈希的做法:
- 把哈希空间看成一个环,比如 0 到 2^32-1。
- 每个服务节点通过 hash 映射到环上。
- 每个数据 key 也 hash 到环上。
- key 顺时针遇到的第一个节点负责这个 key。
- 新增或删除节点时,只影响该节点附近的一段 key。
虚拟节点是把一个真实节点映射成多个虚拟点,例如 odeA#1、 odeA#2。这样节点在环上分布更均匀,节点数量少时也能减少倾斜;同时可以通过虚拟节点数量表达权重。
完整版教学
一、普通取模为什么扩容代价大
假设有 3 台缓存,key 的路由规则是 hash(key) % 3。现在扩容到 4 台,规则变成 hash(key) % 4。同一个 key 的余数大概率变化,于是原来在 A 机器的缓存可能要去 B、C、D 找。结果是大量请求打不到原缓存,全部回源数据库,数据库压力瞬间升高。
这就是普通取模最大的问题:节点数量 N 是公式的一部分,N 一变,映射整体重排。缓存、分片、长连接会话都害怕这种整体重排。
二、一致性哈希如何减少迁移
一致性哈希把哈希空间首尾相连成环。节点在环上占位置,key 也在环上占位置。key 不再对节点数取模,而是顺时针找到第一个节点。
新增节点时,新节点只会接管它逆时针方向上一段区间的 key,其他区间归属不变。删除节点时,原来归它的一段 key 顺时针迁移到下一个节点。这样变更范围从“几乎所有 key”缩小到“一小段 key”。这就是一致性哈希的核心价值:节点变动时最小化数据迁移。
三、为什么必须有虚拟节点
如果真实节点很少,哈希环上的位置可能很不均匀。比如 A、B、C 三个节点刚好挤在一段,A 负责很小区间,C 负责巨大区间,C 就会成为热点。哈希函数再均匀,也挡不住节点样本太少造成的波动。
虚拟节点把一个真实节点拆成很多虚拟节点散布到环上。比如每台机器放 100 个虚拟点,3 台机器就有 300 个点,区间分布会平滑很多。key 命中虚拟节点后,再映射回真实机器。虚拟节点还可以做权重:性能强的机器分配更多虚拟节点,承担更多 key。
四、一致性哈希适合哪些场景
它适合“按 key 路由且希望节点变动影响小”的场景:分布式缓存、分库分表路由、对象存储分片、RPC 长连接会话粘滞、任务分片。尤其是缓存系统,减少扩容时缓存大面积失效非常重要。
但它不是万能的。如果 key 本身有热点,比如某个明星商品被疯狂访问,一致性哈希只会稳定地把热点打到同一台机器,反而可能加重热点。这时需要热点 key 拆分、多级缓存、本地缓存、请求合并等方案。
五、和哈希槽有什么关系
Redis Cluster 使用 16384 个 slot,本质上也是“先把 key 映射到固定槽,再把槽分配给节点”。这和一致性哈希目标类似:节点变化时迁移一部分槽,而不是全量 key 重新计算。区别是 slot 是离散槽位,更方便运维迁移和管理;一致性哈希是环形连续空间,更常见于客户端路由和缓存路由。
六、常见误区与追问
这道题不能只背概念,要把「一致性哈希」放回真实分布式系统里解释:谁发起、谁协调、状态如何变化、失败后怎么兜底,以及它和性能、可用性、一致性的取舍。
| 回答层次 | 要讲清的内容 | 容易漏掉的边界 |
|---|---|---|
| 核心结论 | 一致性哈希把节点和 key 映射到环上,节点增删时只迁移相邻区间数据,降低扩缩容抖动 | 不要停在名词解释 |
| 流程机制 | 计算 key 哈希落点 -> 顺时针找到第一个节点 -> 节点加入分走一段区间 -> 节点下线区间交给后继节点 -> 用虚拟节点改善倾斜 | 说明触发方、参与方、状态变化和兜底 |
| 工程取舍 | 10 个缓存节点普通取模扩容到 11 个会导致大部分 key 重映射,一致性哈希通常只影响新增节点相邻区间 | 分布式基础题不能只背概念,必须落到网络不可靠、节点会故障、数据有副本这些前提 |
一致性哈希 面试拆解:
1. 计算 key 哈希落点
2. 顺时针找到第一个节点
3. 节点加入分走一段区间
4. 节点下线区间交给后继节点
5. 用虚拟节点改善倾斜
记忆钩子:先定义问题,再说明一致性、可用性、分区、复制、时钟和故障模型的取舍;回答时要紧扣「一致性哈希」这道题,不要把相邻概念混成一段泛泛的分布式套话。
- 误区:一致性哈希完全不迁移数据。 它减少迁移范围,但新增或删除节点相关区间仍要迁移。
- 误区:不需要虚拟节点。 真实节点少时容易数据倾斜,虚拟节点能让区间更均匀。
- 误区:一致性哈希只用于缓存。 它也可用于分片、路由、负载分配等场景。
- 追问:为什么普通取模扩容影响大? 节点数变化会改变 key % N 的结果,大量 key 落点改变。
- 追问:虚拟节点怎么工作? 一个真实节点对应多个环上虚拟点,分散区间,降低倾斜。
- 追问:热点 key 怎么办? 一致性哈希解决分布,不解决热点,需要副本、拆分或本地缓存。
七、加强记忆
一致性哈希把节点和 key 放到同一个环上,key 顺时针找节点。它解决普通取模扩缩容时“大量 key 重新映射”的问题,新增/删除节点只影响相邻一段数据。虚拟节点用来打散真实节点在环上的分布,减少倾斜,还能表达节点权重。口诀:取模怕 N 变,哈希环怕倾斜,虚拟节点来摊平。