分布式缓存的一致性Hash的Java实现
关于分布式缓存一致性Hash算法的原理,有很多书籍、博客都有详细的介绍。本文主要是想对一致性Hash算法进行一个小小的实现,方便自己更好的理解。
算法的具体原理如下:
先构造一个长度为2^32的整数环(这个环被称为一致性Hash环),根据节点名称的Hash值(其分布为[0, 2^32-1])将服务器节点放置在这个Hash环上,然后根据数据的Key值计算得到其Hash值(其分布也为[0, 2^32-1]),接着在Hash环上顺时针查找距离这个Key值的Hash值最近的服务器节点,完成Key到服务器的映射查找。
一致性Hash的原理图如下:
第一个版本:不使用虚拟节点的一致性Hash算法的实现
首先了,我们写一个ServerNode类,代表服务器节点。
这个类比较简单,包含两个属性:名字和哈希值
package hash;
public class ServerNode {
private String serverNodeName;
private long serverNodeHash;
public ServerNode(String serverNodeName, long serverNodeHash) {
super();
this.serverNodeName = serverNodeName;
this.serverNodeHash = serverNodeHash;
}
public String getServerNodeName() {
return serverNodeName;
}
public void setServerNodeName(String serverNodeName) {
this.serverNodeName = serverNodeName;
}
public long getServerNodeHash() {
return serverNodeHash;
}
public void setServerNodeHash(long serverNodeHash) {
this.serverNodeHash = serverNodeHash;
}
}
然后,我们就根据最上面所描述的算法进行实现。
可能首先要考虑的问题就是:用什么样的数据结构来存储服务器节点。本文采用的是“排序+List”。在http://www.cnblogs.com/xrq730/p/5186728.html文章中介绍了三种存储结构,第一种为:排序+List;第二种为:遍历+List;第三种为:二叉树(推荐使用)。
上面所了存储结构的事,在ConsistentHashWithoutVirtualNode类中,包含以下几种方法:
1、addServer;添加服务器节点的方法,这个是必须的
2、deleteServer;如果有服务器节点宕机,则在集群中需要删除这个节点
3、hash(),hash函数,这个是必须的。
4、getServerAccordKey;根据指定的key得到其路由到哪个服务器节点上。
具体实现代码如下:
package hash;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.zip.CRC32;
public class ConsistentHashWithoutVirtualNode {
//用来存储服务器节点对象
List<ServerNode> serverNodes= new ArrayList<ServerNode>();
//添加服务器节点
public void addServerNode(String serverNodeName){
if(serverNodeName==null){
return;
}
//利用Hash算法,求出服务器节点的Hash值
long serverNodeHash = getHash(serverNodeName);
ServerNode serverNode = new ServerNode(serverNodeN