
玄虚一致性 hash 多用于诀别式数据存储场景,在集群节点数目发生变化时,进步集群相宜变化的材干。
大多数网站背后服气不是唯有一台工作器提供工作,因为单机的并发量和数据量王人是有限的,是以王人会用多台工作器组成集群来对外提供工作。那么这些工作器需要怎么分拨客户端的恳求呢,这个其实即是负载平衡。然则一般的负载平衡算法是针对扫数工作器上的数据王人是相似的,也即是无法卤莽诀别式存储的场景。
当想要提高系统的容量,就会将数据水平切分到不同的节点来存储,也即是将数据诀别到了不同的节点。比如一个诀别式 KV(key-valu) 缓存系统,某个 key 应该到哪个或者哪些节点上得回,应该是详情的,不是说随便探望一个节点王人不错得到缓存限制的。而 hash 算法就不错很好的完成 k-v 对的存储,因为对并吞个关节字进行哈希盘算推算,每次盘算推算王人是疏通的值,这么就不错将某个 key 详情到一个节点了,不错自豪诀别式系统的负载平衡需求。
#Java #每天一个常识点而一致性 hash 是传统 hash 算法的增强版。
传统hash存在的问题hash 算法最约略的作念法即是进行取模运算,比如诀别式系统中有 3 个节点,就不错基于 hash(key) % 3 公式对数据进行映射。
然则这么,若是节点数目发生了变化(比如现时节点弗成自豪条件了,需要新增一个节点加多容量),也即是在对系统作念扩愉快者缩容时,必须迁徙转换了映射相关的数据,不然会出现查询不到数据的问题。
光显,要科罚这个问题,就需要进行 数据迁徙 ,比如节点的数目从 3 变化为 4 时,需要基于新的盘算推算公式 hash(key) % 4 ,再行对数据和节点作念映射。
假定总和据条数为 M,哈希算法在濒临节点数目变化时,最坏情况下所稀有据王人需要迁徙,是以它的数据迁徙规模是 O(M),这么数据的迁徙资本太高了。
而一致性 hash 算法例是将这种因节点数目变化所需要破耗的退换资本,降至最低
一致性hash一致性 hash 引入了哈希环的宗旨,中枢念念路:
规则了一个哈希环,环的元素由 [0, 2^32 -1] 范围的整数组成将 key,工作节点通过盘算推算映射到哈希环上顺时针办法为 key 寻找相邻的 第一台 工作节点,完成 key -> node 的相关映射比如,下图中的 key-1 映射的位置,往顺时针的办法找到第一个节点即是节点 A。另外两个节点对应相关为:
Key1 -> Node-AKey2 -> Node-BKey3 -> Node-C假定现时新增一个节点,比如节点数目从3加多到了4,新的节点 D 经由哈希盘算推算后映射到了下图中的位置:也即是说,key-1、key-3 王人不受影响,唯有 key-2的数据 需要被迁徙节点 D。
因此,在一致哈希算法中,澳客APP2026世界杯(中国)官方下载若是加多或者移除一个节点,仅影响该节点在哈希环上顺时针相邻的后继节点,其它数据也不会受到影响。这就不错科罚传统 hash 算法中宽阔数据迁徙的问题。
数据歪斜问题然则一致性哈希算法并 不保证节点粗略在哈希环上诀别均匀 ,这么就会带来一个问题,会有宽阔的恳求辘集在一个节点上。
这么扫数的数据王人会恳求到节点 A 上,这就莫得了负载平衡。而且假定节点 A 故障被移除了,那么扫数的数据也王人需要迁徙到节点 B 上
因此,一致性 hash 确乎粗略镌汰节点数目变化对集群合座酿成的影响,但存在 数据歪斜 问题。
引入捏造节点捏造节点的中枢:
将一个物理节点分化成多个捏造节点将捏造节点映射到哈希环受骗 key 掷中捏造节点后,通过捏造节点找到其所属的物理节点也即是说,不再将信得过节点映射到哈希环上,而是将捏造节点映射到哈希环上,并将捏造节点映射到本色节点,是以这里有 两层 的映射相关。
比如:
对节点 A 加上编号来当作捏造节点:A-01、A-02、A-03对节点 B 加上编号来当作捏造节点:B-01、B-02、B-03对节点 C 加上编号来当作捏造节点:C-01、C-02、C-03不错看到这么使得数据诀别愈加平衡。另外若是移除了一个节点 C,也不会发生宽阔的数据迁徙情况,而且能有不同的节点共同分摊系统的变化,因此踏实性更高:
比如,当某个节点被移除时,对应该节点的多个捏造节点均会移除,而这些捏造节点按顺时针办法的下一个捏造节点, 可能会对应不同的信得过节点 ,即这些不同的信得过节点共同分摊了节点变化导致的压力。上图是为了浮浅意会,每个信得过节点仅包含 3 个捏造节点,这么能起到的平衡后果其实很有限。而在本色的工程中,捏造节点的数目会大好多,比如 Nginx 的一致性哈希算法,每个权重为 1 的信得过节点就含有160 个捏造节点。
而且,有了捏造节点后,还不错为硬件树立更好的节点加多权重,比如对权重更高的节点加多更多的捏造机节点即可。
基础已毕public class ConsistentHash {
private final int numberOfReplicas; // 捏造节点数目
// 哈希环,key为捏造节点的哈希值,value为本色节点
private final SortedMap circle = new TreeMap;
快乐彩正版app下载官网/**
* 构造函数
*
* @param numberOfReplicas 捏造节点数目
* @param nodes 本色节点列表
*/
public ConsistentHash(int numberOfReplicas, Collection nodes) {
this.numberOfReplicas = numberOfReplicas;
for (String node : nodes) {
addNode(node);
}
}
// 添加节点
public void addNode(String node) {
for (int i = 0; i
String virtualNode = node + "#" + i;
int hash = getHash(virtualNode);
circle.put(hash, node);
}
}
// 移除节点
public void removeNode(String node) {
for (int i = 0; i
String virtualNode = node + "#" + i;
int hash = getHash(virtualNode);
circle.remove(hash);
}
}
// 获取数据应该存储的节点
public String getNode(String key) {
if (circle.isEmpty) {
return null;
}
// 盘算推算 key 的哈希值 int hash = getHash(key); // 若是莫得大于等于该 hash 值的节点,则复返第一个节点 if (!circle.containsKey(hash)) { SortedMap tailMap = circle.tailMap(hash); hash = tailMap.isEmpty ? circle.firstKey : tailMap.firstKey; } return circle.get(hash); } /** * FNV1_32_HASH 算法 * * @param str 字符串 * @return 哈希值 */ private long getHash(String str) { final int p = 16777619; int hash = (int) 2166136261L; for (int i = 0; i > 7; hash += hash > 17; hash += hash
// 若是算出来的值为负数则取其系数值 if (hash
回来领先,hash 算法不错用来科罚诀别式存储的问题,但若是节点数目发生变化,也将会发生宽阔的数据迁徙。
而一致性 hash 算法即是通过一个首尾贯串的 hash 环科罚传统 hash 算法中宽阔的数据迁徙的问题的,若是加多或者移除一个节点,仅影响该节点在哈希环上顺时针相邻的后继节点,其它数据也不会受到影响。
然则一致性哈希算法并 不保证节点粗略在哈希环上诀别均匀 ,存在 数据歪斜 问题。
因此就引入了捏造节点澳客APP2026世界杯(中国)官方下载,将一个信得过节点映射为多个捏造节点。不再将信得过节点映射到哈希环上,而是将捏造节点映射到哈希环上,从而提高节点的负载平衡度,和系统的踏实性。