Consistency hash Algorithm consistent Hashing
For the original hash algorithm hash%n
So ...
1. Words do not say more directly on the code, the principle or the detailed self-Baidu can
import Cn.pheker.utils.UtilElapsedTime;import Cn.pheker.utils.UtilLogger;import cn.pheker.utils.UtilMD5;import java.util.*;/*** <pre>* Author Cn.pheker* Date 2018/3/19 10:20* Email [email protected]* desc consistent hashing Algorithm ** </pre> */Public class Consistenthashing { private static final long min_node_number = 0;private static final int max_node_number = Integer.max_value;private static int virtual_node_number; //Real nodeprivate List<node> realnodes = new linkedlist<node> ();//Virtual node, hash ringprivate Sortedmap<integer, vnode> circle = new Treemap<integer, vnode> (); private consistenthashing (int vnnumber) {virtual_node_number = vnnumber; } Public static consistenthashing build (int vnnumber) {return new consistenthashing (vnnumber); } Public consistenthashing AddNode (map<string,string> ipports) {set<string> ips = Ipports.keyset ();iterator<string> ipite = Ips.iterator ();While (Ipite.hasnext ()) {String IP = ipite.next ();addNode (IP, Ipports.get (IP)); }return this; } Public consistenthashing addNode (String IP, int port) {addNode (IP, string.valueof (port));return this; } Public consistenthashing addNode (string IP, string port) {node node = new node (IP, port);if (!realnodes.contains (node)) {realnodes.add (node);utillogger.println ("[Node]:" +node.tostring () + "Hash:" +node.hashfnv1_32 ());//Generate Virtual_node_number virtual nodesfor (int i = 0; i < Virtual_node_number; i++) {Vnode Vnode = Node.createvnode (i);Circle.put (Vnode.hashfnv1_32 (), vnode);utillogger.println ("\t[vnode]:" +vnode.tostring () + "Hash:" +vnode.hashfnv1_32 ()); } }return this; } Public void RemoveNode (String ip,string port) {node node = new node (IP, port);for (int i = 0;i<virtual_node_number;i++) {Vnode Vnode = Node.createvnode (i);Circle.remove (Vnode.hashfnv1_32 ()); }Circle.remove (Node.hashfnv1_32 ()); } Public vnode getnode (String IP, int port) {return GetNode (IP, string.valueof (port)); } Public vnode getnode (string IP, string port) {node node = new node (IP, port);int hash = node.hashfnv1_32 ();if (Circle.isempty ()) return null;Sortedmap<integer, vnode> tailmap = Circle.tailmap (hash);int hashkey;if (Tailmap.isempty ()) {HashKey = Circle.firstkey ();}else {HashKey = Tailmap.firstkey ();}//clockwise Nearest nodeVnode Vnode = Circle.get (HashKey);utillogger.println (String.Format ("[%s]:%s ==> [%s]:%s],node.hashfnv1_32 (), node,vnode.hashfnv1_32 (), Vnode));return vnode; } /*** The first node is a server host */Public class Node {String IP;String Port; Public Node (string IP, string port) {this.ip = IP;this.port = port; } Public String GetIP () {return IP; } Public void setIp (String IP) {this.ip = IP; } Public String Getport () {return port; } Public void Setport (String port) {this.port = port; } Public vnode createvnode (int vnnumber) {return new Vnode (IP, port, vnnumber); } @OverridePublic Boolean equals (Object o) {if (this = O) return true;if (o = = NULL | | getclass ()! = O.getclass ()) return false;node Vnode = (node) o;return Objects.equals (IP, vnode.ip) &&objects.equals (port, vnode.port); }@OverridePublic String toString () {return IP + ":" + port; } /*** Use the Fnv1_32_hash algorithm to calculate the hash value of the server, where the Hashcode method cannot be overridden */public int hashfnv1_32 () {String str = UTILMD5.MD5 (this.tostring ());Final int p = 16777619;int hash = (int) 2166136261L;for (int i = 0; i < str.length (); i++)hash = (hash ^ str.charat (i)) * p;hash + = hash <<;Hash ^= Hash >> 7;hash + = hash << 3;Hash ^= hash >>;hash + = hash << 5; //If the calculated value is negative, take its absolute valuesif (hash < 0)hash = Math.Abs (hash);return hash; } } /*** Virtual Node */Public class Vnode extends node{int number; Public vnode (string IP, string port,int number) {Super (IP, port);this.number = number; } Public Node Tonode () {return new Node (ip,port); } @OverridePublic Boolean equals (Object o) {if (this = O) return true;if (o = = NULL | | getclass ()! = O.getclass ()) return false;if (!super.equals (O)) return false;Vnode Vnode = (vnode) o;return number = = Vnode.number; } @Overridepublic int Hashcode () {return Objects.hash (number); } @OverridePublic String toString () {return IP + ":" + port+ "#" +number; } } /*** Check hash distribution uniformity* @return */Public Float Check () {set<integer> ks = Circle.keyset ();int size = Ks.size ();long sum = 0L;for (int hash:ks) {sum + = hash; }double percent = size = = Min_node_number? Min_node_number:(100*2*sum/size)/max_node_number;return float.valueof (String.Format ("%.2f", percent)); } Public static void Main (string[] args) {Utilelapsedtime.test ((), {consistenthashing ch = consistenthashing.build (3);//Add nodeutillogger.println ("------------add Node----------------");Ch.addnode ("10.96.74.187");Ch.addnode ("127.0.0.1", 8080);Ch.addnode ("243.15.155.0", 2150);Ch.addnode ("243.15.155.1", 2150); utillogger.println ("------------is uniform----------------");utillogger.println (Ch.check () + "%"); //Get nodeutillogger.println ("------------get Node----------------");Ch.getnode ("10.96.74.187");Ch.getnode ("123.1.122.253");Ch.getnode ("234.67.80.219", 3306);return "time-consuming calculation complete"; }); } }
2. Results
------------Add node----------------[node]:10.96.74.187: theHash:1695118842[Vnode]:10.96.74.187: the#0Hash:1661313686[Vnode]:10.96.74.187: the#1Hash:1283046442[Vnode]:10.96.74.187: the#2Hash:564332117[Node]:127.0.0.1:8080Hash:678080562[Vnode]:127.0.0.1:8080#0Hash:1731933288[Vnode]:127.0.0.1:8080#1Hash:1369405387[Vnode]:127.0.0.1:8080#2Hash:200594664[Node]:243.15.155.0:2150Hash:1175061629[Vnode]:243.15.155.0:2150#0Hash:134880260[Vnode]:243.15.155.0:2150#1Hash:1677894747[Vnode]:243.15.155.0:2150#2Hash:522817245[Node]:243.15.155.1:2150Hash:1305999210[Vnode]:243.15.155.1:2150#0Hash:1193457699[Vnode]:243.15.155.1:2150#1Hash:279279823[Vnode]:243.15.155.1:2150#2Hash:2115663065------------is uniform----------------98.0%------------Get node----------------[1695118842]:10.96.74.187: the==> [1731933288]:127.0.0.1:8080#0[601034131]:123.1.122.253: -==> [1193457699]:243.15.155.1:2150#0[508181784]:234.67.80.219:3306==> [522817245]:243.15.155.0:2150#2[.104187MS] Time-consuming calculation complete process finished with exit code0
3. Precautions
The code used a few tool classes Utilmd5,utillogger for their own, utilelapsedtime for the calculation time-consuming, can be directly removed.
4. Reference links
An in-depth study of consistency hash algorithm and Java code implementation
Vernacular parsing: Consistent hashing algorithm consistent hashing
Consistency hash Algorithm consistent Hashing