Java Implementation of Consistent Hash

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326079476&siteId=291194637