Consistent Hash算法学习

131 篇文章 2 订阅
34 篇文章 2 订阅
ConsistentHashing算法代码。
一致性哈希(Consistent Hash)
协议简介
一致性哈希算法在1997年由麻省理工学院提出(参见0),设计目标是为了解决因特网中的热点(Hot pot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得DHT可以在P2P环境中真正得到应用。
哈希算法
一致性哈希提出了在动态变化的Cache环境中,哈希算法应该满足的4个适应条件:
平衡性(Balance)
平衡性是指哈希的结果能够尽可能分布到所有的缓存中去,这样可以使得所有的缓存空间都得到利用。很多哈希算法都能够满足这一条件。
单调性(Monotonicity)
单调性是指如果已经有一些内容通过哈希分派到了相应的缓存中,又有新的缓存加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓存中去,而不会被映射到旧的缓存集合中的其他缓冲区。
简单的哈希算法往往不能满足单调性的要求,如最简单的线性哈希:
x → ax + b mod (P)
在上式中,P表示全部缓存的大小。不难看出,当缓存大小发生变化时(从P1到P2),原来所有的哈希结果均会发生变化,从而不满足单调性的要求。
哈希结果的变化意味着当缓存空间发生变化时,所有的映射关系需要在系统内全部更新。而在P2P系统内,缓存的变化等价于Peer加入或退出系统,这一情况在P2P系统中会频繁发生,因此会带来极大计算和传输负荷。单调性就是要求哈希算法能够避免这一情况的发生。
分散性(Spread)
在分布式环境中,终端有可能看不到所有的缓存,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓存上时,由于不同终端所见的缓存范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓存区中。这种情况显然是应该避免的,因为它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。
负载(Load)
负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。
从表面上看,一致性哈希针对的是分布式缓冲的问题,但是如果将缓冲看作P2P系统中的Peer,将映射的内容看作各种共享的资源(数据,文件,媒体流等),就会发现两者实际上是在描述同一问题。
路由算法
在一致性哈希算法中,每个节点(对应P2P系统中的Peer)都有随机分配的ID。在将内容映射到节点时,使用内容的关键字和节点的ID进行一致性哈希运算并获得键值。一致性哈希要求键值和节点ID处于同一值域。最简单的键值和ID可以是一维的,比如从0000到9999的整数集合。
根据键值存储内容时,内容将被存储到具有与其键值最接近的ID的节点上。例如键值为1001的内容,系统中有ID为1000,1010,1100的节点,该内容将被映射到1000节点。
为了构建查询所需的路由,一致性哈希要求每个节点存储其上行节点(ID值大于自身的节点中最小的)和下行节点(ID值小于自身的节点中最大的)的位置信息(IP地址)。当节点需要查找内容时,就可以根据内容的键值决定向上行或下行节点发起查询请求。收到查询请求的节点如果发现自己拥有被请求的目标,可以直接向发起查询请求的节点返回确认;如果发现不属于自身的范围,可以转发请求到自己的上行/下行节点。
为了维护上述路由信息,在节点加入/退出系统时,相邻的节点必须及时更新路由信息。这就要求节点不仅存储直接相连的下行节点位置信息,还要知道一定深度(n跳)的间接下行节点信息,并且动态地维护节点列表。当节点退出系统时,它的上行节点将尝试直接连接到最近的下行节点,连接成功后,从新的下行节点获得下行节点列表并更新自身的节点列表。同样的,当新的节点加入到系统中时,首先根据自身的ID找到下行节点并获得下行节点列表,然后要求上行节点修改其下行节点列表,这样就恢复了路由关系。
讨论
一致性哈希基本解决了在P2P环境中最为关键的问题——如何在动态的网络拓扑中分布存储和路由。每个节点仅需维护少量相邻节点的信息,并且在节点加入/退出系统时,仅有相关的少量节点参与到拓扑的维护中。所有这一切使得一致性哈希成为第一个实用的DHT算法。

但是一致性哈希的路由算法尚有不足之处。在查询过程中,查询消息要经过O(N)步(O(N)表示与N成正比关系,N代表系统内的节点总数)才能到达被查询的节点。不难想象,当系统规模非常大时,节点数量可能超过百万,这样的查询效率显然难以满足使用的需要。换个角度来看,即使用户能够忍受漫长的时延,查询过程中产生的大量消息也会给网络带来不必要的负荷。




源代码:


package heritrix;


import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;


public class ConsistentHash<T> {
//哈希算法
private final HashFunction hashFunction;

//虚拟节点数目
private final int numberOfReplicas;

private final SortedMap<Integer, T> circle = new TreeMap<Integer, T>();

public ConsistentHash(HashFunction hashFunction, int numberOfReplicas, Collection<T> nodes){
this.hashFunction = hashFunction;
this.numberOfReplicas = numberOfReplicas;
for(T node : nodes){
add(node);
}
}


public void add(T node){
for(int i = 0; i < numberOfReplicas; i++){
circle.put(hashFunction.hash(node.toString() + i), node);
}

}


public void remove(T node){
for(int i = 0; i < numberOfReplicas; i++){
circle.remove(hashFunction.hash(node.toString() + i));
}
}

//关键算法
public T get(Object key){
if(circle.isEmpty()){
return null;
}

//计算hash值
int hash = hashFunction.hash(key);

//如果不包括这个hash值
if(!circle.containsKey(hash)){
SortedMap<Integer, T> tailMap = circle.tailMap(hash);
hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); 
}
return circle.get(hash);
}
}





ConsistentHash是一种在分布式系统中解决数据分片、负载均衡的算法,用于解决数据分布和节点动态变化的问题。在Java中,可以通过实现ConsistentHash算法来分配数据并达到负载均衡的效果。 在Java中,可以使用TreeMap或者HashMap作为底层数据结构来实现ConsistentHash算法。TreeMap可以保证数据有序性,HashMap则可以提供更快的插入和查询速度。我们在这里以TreeMap为例来说明ConsistentHash的实现过程。 首先,我们需要创建一个哈希函数,将节点的IP地址或者ID映射为整数,作为节点的哈希值。然后,我们在TreeMap中存储节点的哈希值和对应的物理节点信息。 当有新的数据需要插入时,将数据的哈希值通过哈希函数计算得到对应的整数。然后,在TreeMap中找到大于等于该哈希值的最小键值对应的物理节点,将数据保存在该节点上。 当节点动态增加或删除时,我们需要重新计算所有已存在数据的哈希值,并将数据重新分配到新的节点上,以保持数据的均匀分布。 通过使用ConsistentHash算法,我们可以实现数据的分片存储和负载均衡,使得在节点动态变化的情况下,系统的性能和可扩展性得到有效的提升。 总之,ConsistentHash算法是一种在分布式系统中解决数据分片、负载均衡问题的算法。在Java中,我们可以通过实现ConsistentHash算法,使用TreeMap或者HashMap来实现数据分配和节点动态变化的管理。这样可以有效提高系统的性能和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨鑫newlfe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值