
一致性哈希是一种解决分布式系统中数据分片和负载均衡问题的算法,其核心思想是哈希环与虚拟节点的结合。通过将节点和数据映射到环形哈希空间,实现节点动态变化时仅需局部数据迁移,而非全局重新分配13。
关键设计:
优势:
以下是一个基于TreeMap的简化实现,支持虚拟节点:
import java.util.*;
import java.security.MessageDigest;
public class ConsistentHash<T> {
private final TreeMap<Long, T> ring = new TreeMap<>();
private final int virtualNodes;
private final HashFunction hashFunc;
public ConsistentHash(Collection<T> nodes, int virtualNodes) {
this.virtualNodes = virtualNodes;
this.hashFunc = new MD5Hash();
for (T node : nodes) addNode(node);
}
// 添加节点(生成虚拟节点)
public void addNode(T node) {
for (int i = 0; i < virtualNodes; i++) {
long hash = hashFunc.hash(node.toString() + "#" + i);
ring.put(hash, node);
}
}
// 删除节点
public void removeNode(T node) {
for (int i = 0; i < virtualNodes; i++) {
long hash = hashFunc.hash(node.toString() + "#" + i);
ring.remove(hash);
}
}
// 获取数据归属节点
public T getNode(String key) {
if (ring.isEmpty()) return null;
long hash = hashFunc.hash(key);
SortedMap<Long, T> tailMap = ring.tailMap(hash);
Long nodeHash = tailMap.isEmpty() ? ring.firstKey() : tailMap.firstKey();
return ring.get(nodeHash);
}
// 哈希函数(MD5示例)
private static class MD5Hash implements HashFunction {
public long hash(String key) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(key.getBytes());
return ((digest[3] & 0xFFL) << 24) | ((digest[2] & 0xFFL) << 16)
| ((digest[1] & 0xFFL) << 8) | (digest[0] & 0xFFL);
} catch (Exception e) { throw new RuntimeException(e); }
}
}
interface HashFunction { long hash(String key); }
}指标 | 数值 | 说明 |
|---|---|---|
时间复杂度 | O(log N) | 基于TreeMap的tailMap操作 |
空间复杂度 | O(M*K) | M为物理节点数,K为虚拟节点数 |
容错性 | 仅影响相邻节点数据 | 支持动态增删节点 |
新手入门:
成手进阶:
一致性哈希的优雅在于用数学的确定性应对分布式的不确定性。正如其在Pulsar消息队列中的应用(通过虚拟节点优化Key-Shared模式),这一算法持续推动着分布式系统的演进。无论是新手理解其环状逻辑,还是成手探索虚拟节点的精妙平衡,一致性哈希都是分布式领域不可忽视的基石。