Skip to content

1. 普通 Hash 的问题

text
node = hash(key) % N

N 变化(节点增/删)→ 几乎所有 key 重新映射 → 瞬间大规模缓存失效 → “雪崩”

2. 一致性 Hash 原理

  • 把整个 hash 空间(0 ~ 2³²-1)首尾相接成 闭环
  • 每个节点计算 唯一 hash 落在环上
  • 每个 key 顺时针找 第一个≥自己 hash 的节点
  • 仅影响环上相邻区间,其他 key 保持不动

节点变动时 数据迁移量 ≈ 1/N,雪崩概率大幅下降。

3. 虚拟节点(Virtual Node)(面试重点)

问题:真实节点少 → 环上分布不均 → 数据倾斜 + 负载倾斜
解决:每个物理节点生成 k 个虚拟节点(k=150~200 常用)

  • virtualHash = hash("物理IP#序号")
  • 虚拟节点均匀散落在环上,整体负载方差↓k 倍
  • 增删物理机时,多个虚拟节点间隔移除/加入,进一步平滑迁移量。

4. 代码片段(带虚拟节点,Java)

java
public class ConsistentHash {
    private final SortedMap<Integer, String> ring = new TreeMap<>();
    private final int virtualCnt;

    public ConsistentHash(List<String> nodes, int virtualCnt) {
        this.virtualCnt = virtualCnt;
        for (String node : nodes) add(node);
    }
    private void add(String node) {
        for (int i = 0; i < virtualCnt; i++)
            ring.put(hash(node + "#" + i), node);
    }
    public String get(Object key) {
        int h = hash(key);
        SortedMap<Integer, String> tail = ring.tailMap(h);
        int nodeHash = tail.isEmpty() ? ring.firstKey() : tail.firstKey();
        return ring.get(nodeHash);
    }
    private int hash(Object o) { return o.hashCode() & 0x7fffffff; }
}

5. 面试金句

“一致性哈希把 ‘全体重新映射’ 变成 ‘只动邻居’
虚拟节点把 ‘物理少导致倾斜’ 变成 ‘虚拟多而均匀’, 最终让 增删节点时数据迁移量最小、负载最平滑。”