一致性哈希算法原理与应用
创作时间:
作者:
@小白创作中心
一致性哈希算法原理与应用
引用
CSDN
1.
https://blog.csdn.net/kaige8312/article/details/145732683
一致性哈希算法(Consistent Hashing)是一种广泛应用于分布式系统中的数据分片和负载均衡技术,尤其在缓存系统(如 Redis、Memcached)和分布式数据库(如 DynamoDB)中表现突出。它的核心目标是解决传统哈希算法在节点动态变化时导致的数据大规模迁移问题,从而提升系统的可扩展性和稳定性。
为什么需要一致性哈希?
在传统哈希算法中,假设有 N 个节点,数据通过哈希函数(如 hash(key) % N)分配到某个节点。但若节点数量变化(如节点宕机或新增节点),哈希结果会因模数 N 的改变而完全打乱,导致几乎所有数据需要重新分配。例如:
- 当 N 从 3 变为 4 时,
hash(key) % 3和hash(key) % 4的结果差异巨大,引发大规模数据迁移。
这种问题在分布式系统中会导致:
- 缓存雪崩:大量缓存失效,请求直接压向后端数据库。
- 负载不均衡:新节点可能无法立即承担足够流量,而其他节点可能过载。
一致性哈希的核心思想
一致性哈希通过构建一个环形哈希空间(通常范围是 0∼2的32次方−1),将节点和数据映射到环上,数据按顺时针方向找到最近的节点。这样,节点增减时仅影响相邻区域的数据,而非全局。
(Java中, hashCode() 返回的是一个 int 类型的值,范围是 -2^31 到 2^31 - 1)
关键步骤
- 构建哈希环:将哈希值空间首尾相连形成一个环。
- 映射节点:对节点(如 IP 或名称)哈希,确定其在环上的位置。
- 服务器节点的
hashCode,通过位运算消除符号位,得到一个在哈希环上的位置。节点放置对应位置上。
// 计算哈希值位置
private int hash(String key) {
//在 Java 中,hashCode() 返回的是一个 int 类型的值,范围是 -2^31 到 2^31 - 1(即 -2147483648 到 2147483647)。 这里采用Math.abs取绝对值
// 使用位运算消除符号位,确保哈希码为正整数
return key.hashCode() & 0x7FFFFFFF;
}
- 服务器节点的
hashCode,取绝对值, 得到一个位置。
// 计算位置
private int hash(String key) {
//在 Java 中,hashCode() 返回的是一个 int 类型的值,范围是 -2^31 到 2^31 - 1(即 -2147483648 到 2147483647)。 这里采用Math.abs取绝对值
return Math.abs(key.hashCode());
}
- 路由数据:对数据键(Key)哈希,从环上顺时针查找第一个节点作为归属。
虚拟节点(Virtual Nodes)
若直接映射物理节点到环上,可能出现数据倾斜(节点分布不均)。例如,两个节点可能分别负责环的 80% 和 20% 区域。
解决方案:为每个物理节点创建多个虚拟节点(如 1000 个),分散在环上。数据先找到虚拟节点,再映射到物理节点。
- 优点:虚拟节点越多,负载越均衡。
- 示例:物理节点 A 对应虚拟节点 A1, A2, ..., A1000,B 同理。
一致性哈希的优势
- 动态扩展性:新增节点时,仅影响相邻区间的数据。
- 例如,环上新增节点 D,仅需将原属于节点 B 的部分数据迁移到 D。
- 容错性:节点宕机时,数据自动迁移到下一个节点。
- 负载均衡:通过虚拟节点分散热点,避免单个节点过载。
应用场景
- 分布式缓存:如 Redis Cluster 使用哈希槽(Hash Slot),本质是一致性哈希的变体。
- 负载均衡:如 Nginx 的
hash指令支持一致性哈希分配请求。 - P2P 网络:文件分片存储在最近的节点。
- 服务发现:如 Consul 用一致性哈希路由请求到健康实例。
一致性哈希 vs 传统哈希
场景 | 传统哈希 | 一致性哈希 |
|---|---|---|
节点增减时的数据迁移量 | 全量迁移(1−1/N) | 局部迁移(仅相邻节点受影响) |
负载均衡 | 依赖哈希函数均匀性 | 通过虚拟节点优化,更均衡 |
适用场景 | 节点固定的场景 | 动态伸缩的分布式系统 |
改进与变体
- 带权重的一致性哈希:通过调整虚拟节点数量,让高性能节点承担更多流量。
- Jump Consistent Hash:Google 提出的算法,无需虚拟节点,但仅支持顺序节点增减。
- Rendezvous Hashing:通过计算节点与键的匹配度选择最高分节点,避免环结构。
总结
一致性哈希通过环形拓扑和虚拟节点技术,解决了分布式系统中节点动态变化时的数据路由问题,显著降低了数据迁移成本并提升了负载均衡能力。它是构建高可用、可扩展分布式系统的基石之一。
JAVA实现
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
public class ConsistentHashing {
// 虚拟节点数量
private static final int VIRTUAL_NODES = 1000000;
// 哈希环,使用 TreeMap 来存储,方便查找大于给定 key 的最小节点
private final SortedMap<Integer, String> hashRing = new TreeMap<>();
// 实际节点与虚拟节点的映射关系
private final Map<String, Integer> realToVirtual = new HashMap<>();
// 添加实际节点
public void addNode(String node) {
for (int i = 0; i < VIRTUAL_NODES; i++) {
int virtualNodeHash = hash(node + i);
hashRing.put(virtualNodeHash, node);
realToVirtual.put(node, realToVirtual.getOrDefault(node, 0) + 1);
}
}
// 根据数据找到对应的节点
public String getNode(String data) {
int dataHash = hash(data);
SortedMap<Integer, String> tailMap = hashRing.tailMap(dataHash);
if (tailMap.isEmpty()) {
return hashRing.get(hashRing.firstKey());
}
return tailMap.get(tailMap.firstKey());
}
// 计算哈希值
private int hash(String key) {
//在 Java 中,hashCode() 返回的是一个 int 类型的值,范围是 -2^31 到 2^31 - 1(即 -2147483648 到 2147483647)。 这里采用Math.abs取绝对值
return Math.abs(key.hashCode());
}
public static void main(String[] args) {
ConsistentHashing hashing = new ConsistentHashing();
hashing.addNode("192.168.3.1:server1");
hashing.addNode("192.168.4.1:server2");
hashing.addNode("192.168.5.1:server3");
String data1 = "192.168.0.0:9999";
String data2 = "192.168.0.6:8080";
String data3 = "192.168.9.0:9098";
System.out.println("Data " + data1 + " maps to node: " + hashing.getNode(data1));
System.out.println("Data " + data2 + " maps to node: " + hashing.getNode(data2));
System.out.println("Data " + data3 + " maps to node: " + hashing.getNode(data3));
}
}
热门推荐
右侧交易:理念、方法与适用场景全解析
陶瓷锅的优缺点及使用保养指南
自有资金证明的用途是什么?如何办理自有资金证明?
从香港往内地带东西,你不得不了解的规定
工厂夜班如何规范管理
租房没有水表有没有权利收水费
含有高脂肪的食物有哪些呢
心理学史 | 精神分析的社会文化学派代表人物—弗洛姆
能量管理:一生中最宝贵的财富
不同肤质如何护肤
股息率是什么意思 股息率是不是越高越好
小婴儿吐奶的颜色和频率:正常与异常
牛的生物学特征:为何没有上牙?
美国阿波罗登月计划:从1961年到1972年的伟大工程
哈佛教授发文警告:我们现在就需要控制AI智能体了
巴基斯坦飞行员曾评价歼10C,一语中的:优势显著,但也有缺陷
歼10战机,明明有11个挂点,挂载能力,为何严重不足?
醪糟红枣炖鸡蛋,补血养颜
补养气血绝品啊👍酒酿蛋
小学二年级数学水平,跟着这篇博客也能理解LLM运行原理
理解ADC:Delta-Sigma ADC如何工作?
WiFi各版本的带宽技术解析
WiFi信号强度详解:测量方法、频段特点与优化技巧
多地中小学校园刮起“AI风” 课堂有了哪些新变化?
抑郁症住院治疗的必要性:从心理、医疗、安全到社会支持
调解协议书怎么申请司法确认的
日本人评选的90年代十大动漫
右胫骨下段骨折严重吗
在青藏高原住院三周,我带回了腿上的钢板和钢钉
全面解析美国银行借记卡:使用与优势详解