一致性哈希算法

目的:通过一致性哈希将数据库待处理的数据,通过主键,分配到对应的节点处理

 

public class ConsistentHashCode {

    /**
     * 真实节点数
     */
    private Integer realNodesTotal;

    /**
     * 虚拟节点数量,一个真实节点对应500个虚拟节点
     */
    private static final Integer virtual_node_count = 500;

    /**
     * 实际节点列表如: {0,1,2,3,4}
     */
    private List realNodes;

    /**
     * key 表示服务器的hash值,value表示服务器的虚拟节点名称
     */
    private SortedMap virtualNodes;


    public ConsistentHashCode(Integer realNodesTotal) {
        if (realNodesTotal <= 0) {
            throw new RuntimeException("ConsistentHashCode 初始化失败:节点数量不能小于等于 0");
        }
        this.realNodesTotal = realNodesTotal;
        this.realNodes = new LinkedList<>();
        this.virtualNodes = new TreeMap<>();
        for (int i = 0; i < realNodesTotal; i++) {
            realNodes.add(i);
        }
        realNodes.stream().forEach(realNodes -> {
            for (int i = 0; i < virtual_node_count; i++) {
                String virtualNodeName = realNodes + "&&VN" + String.valueOf(i);
                Integer hash = getHash(virtualNodeName);
                virtualNodes.put(hash, virtualNodeName);
            }
        });
    }

    /**
     * 获取value应该被分配到的节点序号
     *
     * @param value
     * @return
     */
    public Integer getServer(String value) {
        //获取 value的哈希值
        Integer hash = getHash(value);
        //得到大于等于该Hash值的所有Map
        SortedMap subMap = virtualNodes.tailMap(hash);

        if (!subMap.isEmpty()) {
            //获取第一个key,也就是顺时针过去离node最接近的那个节点
            Integer firstKey = subMap.firstKey();
            String virtualNodeName = subMap.get(firstKey);
            return Integer.parseInt(virtualNodeName.substring(0, virtualNodeName.indexOf("&&VN")));
        } else {
            return 0;
        }

    }

    /**
     * 使用FNV1_32_HASH算法计算Hash值
     * @param key
     * @return
     */
    public Integer getHash(String key) {

        final int p = 16777619;
        int hash = (int) 2166136261L;
        for (int i = 0; i < key.length(); i++)
            hash = (hash ^ key.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;
    }
}

 

你可能感兴趣的:(一致性哈希算法)