PackageHash;ImportHash. Shard.node;ImportJava.nio.ByteBuffer;ImportJava.nio.ByteOrder;Importjava.util.ArrayList;ImportJava.util.Iterator;Importjava.util.List;ImportJava.util.SortedMap;ImportJava.util.TreeMap; @SuppressWarnings ("Hiding") Public classshard<node> {//The S class encapsulates information about machine nodes, such as name, password, IP, port, etc. Static PrivateTreemap<long, node> nodes;//mapping of virtual nodes to real nodes Static PrivateTreemap<long, node> Treekey;//key-to-real-node mapping Static Privatelist<node> shards =NewArraylist<node> ();//Real Machine Node Private Final intNode_num = 100;//number of virtual nodes associated with each machine node BooleanFlag =false; @SuppressWarnings ("Static-access") PublicShard (list<node>shards) { Super(); This. Shards =shards; Init (); } Public Static voidMain (string[] args) {Node S1=NewNode ("S1", "192.168.1.1"); Node S2=NewNode ("S2", "192.168.1.2"); Node S3=NewNode ("S3", "192.168.1.3"); Node S4=NewNode ("S4", "192.168.1.4"); Shards.add (S1); Shards.add (S2); Shards.add (S3); Shards.add (S4); Shard<Node> sh =NewShard<node>(shards); System.out.println ("Add clients, starting with 4 hosts, s1,s2,s3,s4 each, with 100 virtual hosts per host:"); Sh.keytonode ("101 Client"); Sh.keytonode ("102 Client"); Sh.keytonode ("103 Client"); Sh.keytonode ("104 Client"); Sh.keytonode ("105 Client"); Sh.keytonode ("106 Client"); Sh.keytonode ("107 Client"); Sh.keytonode ("108 Client"); Sh.keytonode ("109 Client"); Sh.deletes (S4); Sh.adds (S4); System.out.println ("The last client-to-host mapping is:"); Printkeytree (); } /*** Print the mapping of real nodes*/ Public Static voidPrintkeytree () { for(Iterator<long> it =Treekey.keyset (). iterator (); It.hasnext ();) {Long lo=It.next (); System.out.println ("Hash (" +lo+ ") connected to host," +Treekey.get (LO)); } } /*** Generate mappings for virtual nodes*/ Private voidInit () {//initialize a consistent hash ringnodes =NewTreemap<long, node>(); Treekey=NewTreemap<long, node>(); for(inti = 0; I! = Shards.size (); ++i) {//each real machine node requires an associated virtual node FinalNode Shardinfo =Shards.get (i); for(intn = 0; n < Node_num; n++) { //A real Machine node association node_num virtual NodesNodes.put (Hash ("shard-" + shardinfo.name + "-node-" +N), shardinfo); } } } //Add a host Private voidAddS (Node s) {System.out.println ("Increase the host" +s+ "Change:"); for(intn = 0; n < Node_num; n++) {AddS (hash ("shard-" + s.name + "-node-" +N), s); } } //add a virtual node into the ring structure, LG is the virtual node hash value Public voidAddS (Long lg,node s) {SortedMap<long, node> tail =Nodes.tailmap (LG); SortedMap<Long,Node> head =Nodes.headmap (LG); SortedMap<long, node>between; if(Head.size () ==0) {between=Treekey.tailmap (Nodes.lastkey ()); }Else{Long begin=Head.lastkey (); Between= Treekey.submap (Begin,falseLgtrue); } nodes.put (LG, s); for(Iterator<long> it=Between.keyset (). iterator (); It.hasnext ();) {Long lo=It.next (); Treekey.put (Lo, Nodes.get (LG)); System.out.println ("Hash (" +lo+ ") changed to" + "Tail.get (Tail.firstkey ())); } } //Delete Real node is s Public voidDeletes (Node s) {if(s==NULL){ return; } System.out.println ("Remove host" +s+ "Change:"); for(inti=0;i<node_num;i++){ //position of the virtual node where the S node is locatedSortedmap<long, node> tail = Nodes.tailmap (hash ("shard-" + s.name + "-node-" +i)); SortedMap<Long,Node> head = Nodes.headmap (hash ("shard-" + s.name + "-node-" +i)); SortedMap<long, node>between; if(Head.size () ==0) {between=Treekey.tailmap (Nodes.lastkey ()); }Else{Long begin=Head.lastkey (); Long End=Tail.firstkey (); Between= Treekey.submap (Begin,false, End,true);//A collection of all keys for the I virtual node of the S node} nodes.remove (Tail.firstkey ());//Remove the I virtual node of the S node from nodes for(Iterator<long> it =Between.keyset (). iterator (); It.hasnext ();) {Long lo=It.next (); if(tail.size () = = 0) { //if it is a tail node, it is connected to the first contact.Treekey.put (lo, Nodes.firstentry (). GetValue ()); System.out.println ("Hash (" +lo+ ") changed to" + "nodes.firstentry (). GetValue ()); } Else{treekey.put (lo, Tail.get (Tail.firstkey ())); System.out.println ("Hash (" +lo+ ") changed to" + "Tail.get (Tail.firstkey ())); } } } } //map key to real node Public voidKeytonode (String key) {Long HashKey=hash (key); SortedMap<long, node> tail = Nodes.tailmap (HashKey);//find a virtual node clockwise along the ring//if the tail node if(tail.size () = = 0) { //mapping nodes to the first nodetreekey.put (HashKey, Nodes.firstentry (). GetValue ()); SYSTEM.OUT.PRINTLN (Key+ "(hash:" +hashkey+ ") connected to host" +nodes.firstentry (). GetValue ()); return; } treekey.put (HashKey, Tail.get (Tail.firstkey ())); SYSTEM.OUT.PRINTLN (Key+ "(hash:" +hashkey+ ") connected to host" +Tail.get (Tail.firstkey ())); } /*** MurmurHash algorithm, non-cryptographic hash algorithm, high performance, * than the traditional crc32,md5,sha-1 (these two algorithms are cryptographic hash algorithm, the complexity itself is very high, the performance of the damage is unavoidable) * and so on hash The algorithm is much faster, and the collision rate is said to be very low. * http://murmurhash.googlepages.com/ */ Private StaticLong Hash (String key) {Bytebuffer buf=Bytebuffer.wrap (Key.getbytes ()); intSeed = 0X1234ABCD; Byteorder Byteorder=Buf.order (); Buf.order (Byteorder.little_endian); Longm = 0xc6a4a7935bd1e995l; intR = 47; Longh = seed ^ (buf.remaining () *m); LongK; 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); returnh; } Static classnode{String name; String IP; PublicNode (String name,string IP) { This. Name =name; This. IP =IP; } @Override PublicString toString () {return This. name+ "-" + This. IP; } }}
Java Implementation Hash Consistency algorithm