哈希
hash取模算法
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("192.168.1.1"); list.add("192.168.1.2"); list.add("192.168.1.3"); //String topic = "aaaaaaaaaaaaaaaa"; //String topic = "bbbbbbbbbbbbbbbb"; String topic = "cccccccccccccccc"; int abs = Math.abs(topic.hashCode()); int result = abs % list.size(); System.out.println(list.get(result)); }
一致性hash算法
import java.util.LinkedList; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; /** * @author zfang * @date 2021/9/9 16:12 */ public class ConsistencyHashing { // 虚拟节点的个数 private static final int VIRTUAL_NUM = 5; // 虚拟节点分配,key是hash值,value是虚拟节点服务器名称 private static final SortedMap<Integer, String> shards = new TreeMap<>(); // 真实节点列表 private static final List<String> realNodes = new LinkedList<>(); //模拟初始服务器 private static final String[] servers = {"192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.5", "192.168.1.6"}; static { for (String server : servers) { realNodes.add(server); System.out.println("真实节点[" + server + "] 被添加"); for (int i = 0; i < VIRTUAL_NUM; i++) { String virtualNode = server + "&&VN" + i; int hash = getHash(virtualNode); shards.put(hash, virtualNode); System.out.println("虚拟节点[" + virtualNode + "] hash:" + hash + ",被添加"); } } } /** * 获取被分配的节点名 * * @param node * @return */ public static String getServer(String node) { int hash = getHash(node); Integer key = null; SortedMap<Integer, String> subMap = shards.tailMap(hash); if (subMap.isEmpty()) { key = shards.lastKey(); } else { key = subMap.firstKey(); } String virtualNode = shards.get(key); return virtualNode.substring(0, virtualNode.indexOf("&&")); } /** * 添加节点 * * @param node */ public static void addNode(String node) { if (!realNodes.contains(node)) { realNodes.add(node); System.out.println("真实节点[" + node + "] 上线添加"); for (int i = 0; i < VIRTUAL_NUM; i++) { String virtualNode = node + "&&VN" + i; int hash = getHash(virtualNode); shards.put(hash, virtualNode); System.out.println("虚拟节点[" + virtualNode + "] hash:" + hash + ",被添加"); } } } /** * 删除节点 * * @param node */ public static void delNode(String node) { if (realNodes.contains(node)) { realNodes.remove(node); System.out.println("真实节点[" + node + "] 下线移除"); for (int i = 0; i < VIRTUAL_NUM; i++) { String virtualNode = node + "&&VN" + i; int hash = getHash(virtualNode); shards.remove(hash); System.out.println("虚拟节点[" + virtualNode + "] hash:" + hash + ",被移除"); } } } /** * FNV1_32_HASH算法 */ 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; } public static void main(String[] args) { //模拟客户端的请求 String[] nodes = {"127.0.0.1", "10.9.3.253", "192.168.10.1"}; for (String node : nodes) { System.out.println("[" + node + "]的hash值为" + getHash(node) + ", 被路由到结点[" + getServer(node) + "]"); } // 添加一个节点(模拟服务器上线) addNode("192.168.1.7"); // 删除一个节点(模拟服务器下线) delNode("192.168.1.2"); for (String node : nodes) { System.out.println("[" + node + "]的hash值为" + getHash(node) + ", 被路由到结点[" + getServer(node) + "]"); } } }