一致性哈希java实现
来源:互联网 发布:js禁止文本框输入 编辑:程序博客网 时间:2024/05/16 11:20
该client采用TreeMap存储所有节点,模拟一个环形的逻辑关系。在这个环中,节点之前是存在顺序关系的,所以TreeMap的key必须实现Comparator接口。
那节点是怎样放入这个环中的呢?
Java代码
//对所有节点,生成nCopies个虚拟结点 for(Node node : nodes) { //每四个虚拟结点为一组,为什么这样?下面会说到 for(int i=0; i<nCopies / 4; i++) { //getKeyForNode方法为这组虚拟结点得到惟一名称 byte[] digest=HashAlgorithm.computeMd5(getKeyForNode(node, i)); /** Md5是一个16字节长度的数组,将16字节的数组每四个字节一组, 分别对应一个虚拟结点,这就是为什么上面把虚拟结点四个划分一组的原因*/ for(int h=0;h<4;h++) { //对于每四个字节,组成一个long值数值,做为这个虚拟节点的在环中的惟一key Long k = ((long)(digest[3+h*4]&0xFF) << 24) | ((long)(digest[2+h*4]&0xFF) << 16) | ((long)(digest[1+h*4]&0xFF) << 8) | (digest[h*4]&0xFF); allNodes.put(k, node); } } }
上面的流程大概可以这样归纳:四个虚拟结点为一组,以getKeyForNode方法得到这组虚拟节点的name,Md5编码后,每个虚拟结点对应Md5码16个字节中的4个,组成一个long型数值,做为这个虚拟结点在环中的惟一key。第12行k为什么是Long型的呢?呵呵,就是因为Long型实现了Comparator接口。
处理完正式结点在环上的分布后,可以开始key在环上寻找节点的游戏了。
对于每个key还是得完成上面的步骤:计算出Md5,根据Md5的字节数组,通过Kemata Hash算法得到key在这个环中的位置。
Java代码
final Node rv; byte[] digest = hashAlg.computeMd5(keyValue); Long key = hashAlg.hash(digest, 0); //如果找到这个节点,直接取节点,返回 if(!ketamaNodes.containsKey(key)) { //得到大于当前key的那个子Map,然后从中取出第一个key,就是大于且离它最近的那个key SortedMap<Long, Node> tailMap=ketamaNodes.tailMap(key); if(tailMap.isEmpty()) { key=ketamaNodes.firstKey(); } else { key=tailMap.firstKey(); } //在JDK1.6中,ceilingKey方法可以返回大于且离它最近的那个key //For JDK1.6 version // key = ketamaNodes.ceilingKey(key); // if (key == null) { // key = ketamaNodes.firstKey(); // } } rv=allNodes.get(key);
引文中已详细描述过这种取节点逻辑:在环上顺时针查找,如果找到某个节点,就返回那个节点;如果没有找到,则取整个环的第一个节点。
测试结果
测试代码是自己整理的,主体方法没有变
分布平均性测试:测试随机生成的众多key是否会平均分布到各个结点上
测试结果如下:
Java代码
1. Nodes count : 5, Keys count : 100000, Normal percent : 20.0%
2. -------------------- boundary ----------------------
3. Node name :node1 - Times : 20821 - Percent : 20.821001%
4. Node name :node3 - Times : 19018 - Percent : 19.018%
5. Node name :node5 - Times : 19726 - Percent : 19.726%
6. Node name :node2 - Times : 19919 - Percent : 19.919%
7. Node name :node4 - Times : 20516 - Percent : 20.516%
最上面一行是参数说明,节点数目,总共有多少key,每个节点应该分配key的比例是多少。下面是每个结点分配到key的数目和比例。
多次测试后发现,这个Hash算法的节点分布还是不错的,都在标准比例左右徘徊,是个合适的负载均衡算法。
节点增删测试:在环上插入N个结点,每个节点nCopies个虚拟结点。随机生成众多key,在增删节点时,测试同一个key选择相同节点的概率
测试如果如下:
Java代码
1. Normal case : nodes count : 50
2. Added case : nodes count : 51
3. Reduced case : nodes count : 49
4. ------------ boundary -------------
5. Same percent in added case : 93.765%
6. Same percent in reduced case : 93.845%
上面三行分别是正常情况,节点增加,节点删除情况下的节点数目。下面两行表示在节点增加和删除情况下,同一个key分配在相同节点上的比例(命中率)。
多次测试后发现,命中率与结点数目和增减的节点数量有关。同样增删结点数目情况下,结点多时命中率高。同样节点数目,增删结点越少,命中率越高。这些都与实际情况相符。
- 一致性哈希java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- Java实现一致性哈希consistentHash
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与Java实现
- 一致性哈希算法与java实现
- 一致性哈希及java实现
- 一致性哈希算法与Java实现
- dom4j解析XML实例
- 开发中SVN使用规范
- linux 安装redis 部署 启动 停止
- 设置openwrt应用程序开机和崩溃时自动启动
- 彻底卸载Mysql 服务器
- 一致性哈希java实现
- 可编辑可自动匹配的联动下拉框实现
- mybatis插入数据之后获得主键值
- SWF文件格式2(中文翻译版)
- Animation动画详解(九)——联合动画的代码实现
- 尽量用static const替代预处理指令
- leetcode--Reverse Bits
- 第一天
- 微信公众平台开发教程