Skip to content
进阶

一句话答案

将节点映射到哈希环,key 顺时针找最近节点,增删节点只影响相邻数据;虚拟节点解决数据倾斜。

核心要点

传统哈希取模的问题:

hash(key) % N(N = 节点数量)

当节点数量变化时(新增或下线一台机器):
  N 变了 → 几乎所有 key 的映射都变了 → 大量缓存失效 → 缓存雪崩
  例如:3 台变 4 台,约 75% 的 key 需要重新映射

一致性哈希(Consistent Hashing)原理:

① 构建哈希环(Hash Ring):
   将哈希值空间组织成一个 0 ~ 2^32-1 的环

② 节点映射到环上:
   对每个节点的 IP/名称进行哈希,映射到环上的某个位置

③ Key 映射规则:
   对 key 进行哈希 → 在环上顺时针找到第一个节点 → 该节点负责存储这个 key

示意图:
                    0

            Node C ─●─── Key1 → 顺时针找到 Node A

      2^32*3/4 ─────┼───── 2^32*1/4

         Key3 ──●   │   ●── Node A


            Node B ─●─── Key2 → 顺时针找到 Node B

                 2^32/2

新增/删除节点时:
  只影响该节点在环上相邻的一小段区间的 key 映射
  大部分 key 的映射不变 → 最小化缓存失效

为什么需要虚拟节点?

问题:节点数量少时,哈希环上节点分布不均匀 → 数据倾斜

示例(3 个节点,分布不均):
  Node A 负责 60% 的环空间
  Node B 负责 30% 的环空间
  Node C 负责 10% 的环空间
  → 数据严重倾斜,Node A 压力巨大

解决方案——虚拟节点(Virtual Node):
  每个物理节点映射为多个虚拟节点(如 150~200 个)
  Node A → VN_A_1, VN_A_2, VN_A_3, ..., VN_A_150
  Node B → VN_B_1, VN_B_2, VN_B_3, ..., VN_B_150
  Node C → VN_C_1, VN_C_2, VN_C_3, ..., VN_C_150

  虚拟节点均匀分散在哈希环上 → 各物理节点负责的数据量趋于均匀

效果:
  虚拟节点数量越多 → 数据分布越均匀
  一般 150~200 个虚拟节点/物理节点就能达到较好的均匀度

一致性哈希的应用场景:

场景说明
缓存集群分片Redis Cluster 之前的客户端分片(如 Jedis ShardedPool)
负载均衡Nginx upstream 的 consistent_hash 模块
分布式存储Cassandra、Amazon Dynamo 的数据分片
CDN 节点选择根据内容 URL 哈希选择缓存节点
追问与易错

追问方向:

  • 虚拟节点数量设多少?
  • 怎么处理节点负载不均?
  • Redis Cluster 为什么用哈希槽?

易错点:

  • ❌ 一致性哈希完全均匀——没有虚拟节点时可能倾斜
  • ❌ 混淆一致性哈希和哈希槽

💡 记忆锚点

想象一个钟表盘:节点是钟面上的刻度,数据沿顺时针找最近的刻度存放。加减一个刻度只影响相邻那一小段弧,不像取模法那样全盘洗牌。刻度太少分布不均怎么办?每个真刻度变出150个虚拟刻度均匀撒满表盘,数据就不会扎堆了。