There are many explanations about consistent hashing, and it is not difficult to understand. For details, you can read this article written by others.
【转】http://limitlee.iteye.com/blog/1961385
I wrote a java implementation process myself and recorded it.
package com.xjw.consistent.hash; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.apache.commons.codec.digest.DigestUtils; public class ConsistentHash { private SortedMap<Integer, String> serverNodeMap = null; private final static int VIRTUAL_NODE_NUMBER = 5; public void getServerNodeWithoutVirtualNode(List<String> servers) { serverNodeMap = new TreeMap<>(); for (String string : servers) { serverNodeMap.put(hash(string), string); } } public void getServerNodeWithVirtualNode(List<String> servers) { serverNodeMap = new TreeMap<>(); for (String string : servers) { for (int i = 0; i < VIRTUAL_NODE_NUMBER; i++) { String virtualNodeName = string + ":" + i; serverNodeMap.put(hash(virtualNodeName), string); } } } public String getServerName(String data) { int dataHash = hash(data); SortedMap<Integer, String> subMap = serverNodeMap.tailMap(dataHash); int serverHash = 0; if (subMap == null || subMap.size() == 0) { serverHash = serverNodeMap.firstKey(); }else { serverHash = subMap.firstKey(); } String serverName = serverNodeMap.get(serverHash); return serverName; } /** * Hash calculation, use md5 here to get the hashcode, this md5 needs to depend on the codec package of apache * @param str * @return */ public int hash(String str) { return DigestUtils.md5Hex(str).hashCode(); } public static void main(String[] args) { List<String> servers = new ArrayList<>(); servers.add("192.168.1.1"); servers.add("192.168.1.2"); servers.add("192.168.1.3"); servers.add("192.168.1.4"); servers.add("192.168.1.5"); servers.add("192.168.1.6"); List<String> datas = new ArrayList<>(); datas.add("Henan"); datas.add("Shandong"); datas.add("天津"); datas.add("Beijing"); datas.add("Shanghai"); datas.add("Guangzhou"); datas.add("Wuhai"); datas.add("Wuhan"); datas.add("Hefei"); datas.add("Changsha"); ConsistentHash consistentHash = new ConsistentHash(); System.out.println("No virtual node: "); consistentHash.getServerNodeWithoutVirtualNode(servers); consistentHash.printDataAndServerNode(servers, datas, consistentHash); System.out.println("There are virtual nodes: "); consistentHash.getServerNodeWithVirtualNode(servers); consistentHash.printDataAndServerNode(servers, datas, consistentHash); servers.remove(0); System.out.println("After removing the first node: "); System.out.println("No virtual node: "); consistentHash.getServerNodeWithoutVirtualNode(servers); consistentHash.printDataAndServerNode(servers, datas, consistentHash); System.out.println("There are virtual nodes: "); consistentHash.getServerNodeWithVirtualNode(servers); consistentHash.printDataAndServerNode(servers, datas, consistentHash); } public void printDataAndServerNode(List<String> servers, List<String> datas, ConsistentHash consistentHash) { Map<String, String> result = new HashMap<>(); for (String data : datas) { String serverName = consistentHash.getServerName(data); if (!result.containsKey(serverName)) { result.put(serverName, data); }else { result.put(serverName, result.get(serverName) + "," + data); } } for (Entry<String, String> entry : result.entrySet()) { System.out.println(entry.getKey()+":"+entry.getValue()); } } }
The output is:
Without virtual nodes:
192.168.1.1: Henan, Shandong, Guangzhou
192.168.1.3: Tianjin, Hefei, Changsha
192.168.1.4: Beijing, Shanghai, Wuhai
192.168.1.6: Wuhan
With virtual nodes:
192.168.1.1: Shanghai
192.168.1.3: Henan, Tianjin, Guangzhou
192.168.1.2: Shandong, Beijing, Wuhai, Hefei
192.168.1.5: Wuhan
192.168.1.6: Changsha
After removing the first node:
Without virtual nodes:
192.168.1.3: Henan, Shandong, Tianjin, Guangzhou, Hefei, Changsha
192.168.1.4: Beijing, Shanghai, Wuhai
192.168.1.6: Wuhan
With virtual nodes:
192.168.1.3: Henan, Tianjin, Guangzhou
192.168.1.2: Shandong, Beijing, Wuhai, Hefei
192.168.1.5: Shanghai, Wuhan
192.168.1.6: Changsha