java hash 算法实现_java实现hash一致性算法

本文介绍了一致性哈希算法在处理虚拟节点与真实服务器之间的映射,通过FNV1_32_HASH计算服务器的哈希值,并演示如何解决哈希碰撞问题。通过随机生成节点,展示了如何将节点路由到正确的服务器,以及统计各服务器负载情况。
摘要由CSDN通过智能技术生成

importorg.apache.commons.lang3.RandomUtils;importorg.apache.commons.lang3.StringUtils;import java.util.*;/*** 一致性hash*/

public classConsistentHashWithVirtualNode {/*** 待添加入Hash环的服务器列表*/

private static String[] SERVERS = {"192.168.1.2:6379", "192.168.1.3:6379"};/*** key表示服务器的hash值,value表示虚拟节点的名称*/

private static SortedMap HASH_CIRCLE = new TreeMap();/*** 用于结果统计*/

private static Map result = new HashMap();/*** 每个真实节点对应虚拟节点数*/

private static Integer VIRTUAL_NODES_NUM = 150;/*** 使用FNV1_32_HASH算法计算服务器的Hash值*/

private static intgetHash(String str) {final int p = 16777619;int hash = (int) 2166136261L;for (int i = 0; i < str.length(); i++)

hash= (hash ^ str.charAt(i)) *p;

hash+= hash << 13;

hash^= hash >> 7;

hash+= hash << 3;

hash^= hash >> 17;

hash+= hash << 5;//如果值为负数则取其绝对值

if (hash < 0)

hash=Math.abs(hash);returnhash;

}static{for (int i = 0; i < SERVERS.length; i++) {for (Integer j = 0; j < VIRTUAL_NODES_NUM; j++) {

setServer(SERVERS[i]+ "vn" +j);

}

}

}private static voidsetServer(String ip) {

setServer(ip,null);

}private static voidsetServer(String ip, Integer hash) {

hash= hash != null ?getHash(hash.toString()) : getHash(ip);if(StringUtils.isBlank(HASH_CIRCLE.get(hash))) {

HASH_CIRCLE.put(hash, ip);

System.out.println("[" + ip + "]加入sortedMap中, 其Hash值为" +hash);

}else{//解决hash碰撞

setServer(ip, hash);

}

}public static voidmain(String[] args) {for (int i = 0; i < 50; i++) {long nodes =RandomUtils.nextLong();

String server=getServer(nodes);

String realServer= server.split("vn")[0];

System.out.println("[" + nodes + "]的hash值为" + getHash("" + nodes) + ", 被路由到虚拟结点[" + server + "], 真实结点[" + realServer + "]");

result.put(realServer, (result.get(realServer)== null ? 0 : result.get(realServer)) + 1);

}

result.forEach((k, v)->{

System.out.println("结点[" + k + "]上有" +v);

});

}public staticString getServer(Object node) {

String ip=HASH_CIRCLE.get(HASH_CIRCLE.firstKey());//得到带路由的结点的Hash值

int hash =getHash(node.toString());//得到大于该Hash值的所有Map

SortedMap subMap =HASH_CIRCLE.tailMap(hash);if (!subMap.isEmpty()) {//第一个Key就是顺时针过去离node最近的那个结点

Integer i =subMap.firstKey();

ip=subMap.get(i);

}//返回对应的服务器名称

returnip;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值