public class ConsistenHashWithVN { private static String[] servers = { "192.168.0.0:111", "192.168.0.1:111", "192.168.0.2:111", "192.168.0.3:111", "192.168.0.4:111", }; private static List<String> virtualNodes = new ArrayList<>(); private static int VNSIZE = 5; private static SortedMap<Integer, String> sortedMap = new TreeMap<>(); /**初始化**/ static { for(String str : servers) { for(int i = 0; i < VNSIZE; i++) { String vNode = str + "#" + i; sortedMap.put(getHash(vNode),vNode); System.out.println("[" + vNode + "] 加入集合,其hash值为" + getHash(vNode)); } } System.out.println(); } /** * 使用FNV1_32_HASH算法计算服务器的Hash值 * @param str * @return */ private static int getHash(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); // return hash; return Math.abs(md5(str).hashCode()); } /** * 使用MD5放大差异 * @param content * @return */ private static String md5(String content) { byte[] secretBytes = null; try{ MessageDigest md = MessageDigest.getInstance("MD5"); md.update(content.getBytes()); secretBytes = md.digest(); }catch (NoSuchAlgorithmException e){ throw new RuntimeException("没有这个md5算法"); } String md5Code = new BigInteger(1, secretBytes).toString(16); return md5Code; } private static String getServer(String node) { int hash = getHash(node); /**得到大于该hash值的所有k-v*/ SortedMap<Integer, String> subMap = sortedMap.tailMap(hash); /**找打顺时针第一个大于hash值的虚拟节点**/ Integer i = subMap.firstKey(); String vNode = subMap.get(i); return vNode.substring(0,vNode.indexOf("#")); } public static void main(String[] args) { String[] nodes = { "127.0.0.1:1111", "221.226.0.1:2222", "10.211.0.1:3333" }; for(int i = 0; i < nodes.length; i++) { System.out.println("[" + nodes[i] + "]的hash值为" + getHash(nodes[i]) + ", 被路由到节点[" + getServer(nodes[i]) + "]"); } } }