public class LoadBalanceManager { private static TreeMap<Long, Node> nodes; // 虚拟节点到真实节点的映射 private static TreeMap<Long, Node> treeKey; // key到真实节点的映射 private static final int NODE_NUM = 10; // 每个机器节点关联的虚拟节点个数 /** * 初始化方法,将作为节点的机器List传入作为参数 * @param nodeList */ public LoadBalanceManager(List<Node> nodeList) { nodes = new TreeMap<Long, Node>(); treeKey = new TreeMap<Long, Node>(); for (Node node : nodeList) { for (int n = 0; n < NODE_NUM; n++) { // 一个真实机器节点关联NODE_NUM个虚拟节点 nodes.put(hash("SHARD-" + node.getIp() + "-NODE-" + n), node); } } } /** * 映射key到真实节点 * @param ip */ public void loadBalance(String ip) { SortedMap<Long, Node> tail = nodes.tailMap(hash(ip)); // 沿环的顺时针找到一个虚拟节点 if (tail.size() == 0) { // 如果此ip的hash值比任何一个节点的值都大,则取第一个节点 Node first = nodes.firstEntry().getValue(); treeKey.put(hash(ip), first); System.out.println(ip + "(hash: " + hash(ip) + ")连接到主机->" + first); return; } treeKey.put(hash(ip), tail.get(tail.firstKey())); System.out.println(ip + "(hash: " + hash(ip) + ")连接到主机->" + tail.get(tail.firstKey())); } /** * 增加一个主机 * * @param node */ public void addNode(Node node) { System.out.println("增加主机" + node + "的变化:"); for (int n = 0; n < NODE_NUM; n++) { Long key = hash("SHARD-" + node.getIp() + "-NODE-" + n); addS(key, node); } } /** * 删除真实节点 * * @param node */ public void deleteNode(Node node) { if (node == null) { return; } System.out.println("删除主机" + node + "的变化:"); for (int i = 0; i < NODE_NUM; i++) { // 定位s节点的第i的虚拟节点的位置 Long key = hash("SHARD-" + node.getIp() + "-NODE-" + i); SortedMap<Long, Node> tail = nodes.tailMap(key); SortedMap<Long, Node> head = nodes.headMap(key); Long begin = 0L; Long end = 0L; SortedMap<Long, Node> between; if (head.size() == 0) { between = treeKey.headMap(nodes.firstKey()); end = tail.firstKey(); tail.remove(end); // nodes.remove(end);// 从nodes中删除s节点的第i个虚拟节点 } else { begin = head.lastKey(); end = tail.firstKey(); tail.remove(end); between = treeKey.subMap(begin, end);// 在s节点的第i个虚拟节点的所有key的集合 } for (Iterator<Long> it = between.keySet().iterator(); it.hasNext();) { Long lo = it.next(); treeKey.put(lo, tail.get(tail.firstKey())); System.out.println("hash(" + lo + ")改变到->" + tail.get(tail.firstKey())); } } } /** * 添加一个虚拟节点进环形结构,lg为虚拟节点的hash值 * * @param hashKey * @param node */ private void addS(Long hashKey, Node node) { SortedMap<Long, Node> tail = nodes.tailMap(hashKey); SortedMap<Long, Node> head = nodes.headMap(hashKey); Long begin = 0L; SortedMap<Long, Node> between; if (head.size() == 0) { between = treeKey.headMap(hashKey); } else { begin = head.lastKey(); between = treeKey.subMap(begin, hashKey); } nodes.put(hashKey, node); for (Iterator<Long> it = between.keySet().iterator(); it.hasNext();) { Long lo = it.next(); treeKey.put(lo, nodes.get(hashKey)); System.out.println("hash(" + lo + ")改变到->" + tail.get(tail.firstKey())); } } /** * MurMurHash算法,是非加密HASH算法,性能很高, * 比传统的CRC32,MD5,SHA-1(这两个算法都是加密HASH算法,复杂度本身就很高,带来的性能上的损害也不可避免) * 等HASH算法要快很多,而且据说这个算法的碰撞率很低. */ private Long hash(String key) { ByteBuffer buf = ByteBuffer.wrap(key.getBytes()); int seed = 0x1234ABCD; ByteOrder byteOrder = buf.order(); buf.order(ByteOrder.LITTLE_ENDIAN); long m = 0xc6a4a7935bd1e995L; int r = 47; long h = seed ^ (buf.remaining() * m); long k; while (buf.remaining() >= 8) { k = buf.getLong(); k *= m; k ^= k >>> r; k *= m; h ^= k; h *= m; } if (buf.remaining() > 0) { ByteBuffer finish = ByteBuffer.allocate(8).order( ByteOrder.LITTLE_ENDIAN); finish.put(buf).rewind(); h ^= finish.getLong(); h *= m; } h ^= h >>> r; h *= m; h ^= h >>> r; buf.order(byteOrder); return h; } }