一致性哈希实现

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]) + "]");
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Wengzhengcun/article/details/89494513