All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.linmoure.utils.hash.ConsistentHash Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
package io.github.linmoure.utils.hash;

import java.util.Set;
import java.util.TreeMap;

/**
 * @author lihenglin
 * 一致性hash的实现
 * Java implementation of consistent-hashing
 */
public class ConsistentHash {
    private static final int DEFAULT_VIRTUAL_COUNT = 5;

    /**
     * 设置每个节点的虚拟节点个数,该参数默认是100
     */
    private int virtualCount = DEFAULT_VIRTUAL_COUNT;

    /**
     * 设置一致性HASH的算法,默认采用 KETAMA_HASH
     * 对于一致性HASH而言选择的HASH算法首先要考虑发散度其次再考虑性能
     */
    private final HashAlgorithm alg;

    private final Set nodeSet;  //节点列表

    private final TreeMap nodeMap;


    private ConsistentHash(int virtualCount, Set nodeSet) {
        this.virtualCount = virtualCount;
        this.nodeSet = nodeSet;
        this.alg = HashAlgorithm.KETAMA_HASH;
        nodeMap = new TreeMap();
        buildHashCircle();
    }

    private ConsistentHash(int virtualCount, Set nodeSet, HashAlgorithm alg) {
        this.virtualCount = virtualCount;
        this.nodeSet = nodeSet;
        this.alg = alg;
        nodeMap = new TreeMap();
        buildHashCircle();
    }

    /**
     * Get singleton of ConsistentHash
     * 获取ConsistentHash的单例对象
     *
     * @param virtualCount 虚拟节点个数
     * @param nodeSet      虚拟节点列表
     * @return ConsistentHash
     */
    public static ConsistentHash getInstance(int virtualCount, Set nodeSet) {
        return new ConsistentHash(virtualCount, nodeSet);
    }

    public static ConsistentHash getInstance(int virtualCount, Set nodeSet, HashAlgorithm alg) {
        return new ConsistentHash(virtualCount, nodeSet, alg);
    }

    /**
     * 构建一致性HASH环
     */
    private void buildHashCircle() {
        if (nodeSet == null) return;
        for (Node node : nodeSet) {
            for (int i = 0; i < virtualCount; i++) {
                long nodeKey = this.alg.hash(node.toString() + "-" + i);
                nodeMap.put(nodeKey, node);
            }
        }
    }

    /**
     * 沿环的顺时针找到虚拟节点
     *
     * @param key key
     * @return io.github.linmoure.utils.hash.Node
     */
    public Node findNodeByKey(String key) {
        final Long hash = this.alg.hash(key);
        Long target = hash;
        if (!nodeMap.containsKey(hash)) {
            target = nodeMap.ceilingKey(hash);
            if (target == null && !nodeMap.isEmpty()) {
                target = nodeMap.firstKey();
            }
        }
        return nodeMap.get(target);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy