There is no such thing as perfect programming, but we shouldn’t be discouraged because programming is a constant pursuit of perfection.

  1. Intent: Server load balancing to distribute requests more evenly and improve server scalability
  2. Schematic diagram:

  3. Procedure: Create multiple virtual nodes for each server (the more evenly distributed the better). Obtain the hash value to form a hash ring. When a request is received, put the hash value of the request key into the ring for judgment and find the nearest virtual node clockwise. When a server is added or removed, it only affects nearby nodes and does not have a big impact on overall uniformity. And the more servers there are, the more evenly requests are distributed.
  4. The instance
public class ConsistentHash { private static TreeMap<Long, String> treeMap = new TreeMap<>(); Public static void main(String[] args) {String ipPre = "192.168.2."; // Add virtual nodes for each service, hash ring for (int I = 0; i < 10; i ++) { put(100, ipPre + i); } // Count the number of random requests received by each service Map<String, Integer> countMap = new HashMap<>(); for (int i = 0; i < 10000; i ++) { String ip = get(hash(UUID.randomUUID().toString()+i)); countMap.compute(ip, (a, b) -> { if (null == b) return 1; return b + 1; }); } countMap.forEach((a, b) -> { System.out.println("ip = " + a + ", count = " + b); }); } public static void put (int n, String ip) { for (int i = 0; i < n; i ++) { treeMap.put(hash((ip+i)), ip); } } public static void remove (int n, String ip) { for (int i = 0; i < n; i++) { treeMap.remove(hash.hash((ip+i))); } } public static String get (Long key) { if (treeMap.containsKey(key)) return treeMap.get(key); SortedMap<Long, String> tailMap = treeMap.tailMap(key); key = tailMap.isEmpty() ? treeMap.firstKey() : tailMap.firstKey(); return treeMap.get(key); } public static 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; }}Copy the code

Running results:

IP = 192.168.2.2, count = 1044 IP = 192.168.2.1, count = 1119 IP = 192.168.2.8, IP = 192.168.2.7, count = 859 IP = 192.168.2.9, count = 1033 IP = 192.168.2.4, IP = 192.168.2.6, count = 890 IP = 192.168.2.5, count = 918Copy the code

Want to see more? Please visit:Design patterns