java實現hash一致性演算法

來源:互聯網
上載者:User

標籤:

package hash;import hash.Shard.Node;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.SortedMap;import java.util.TreeMap;@SuppressWarnings("hiding")public class Shard<Node> { // S類封裝了機器節點的資訊 ,如name、password、ip、port等    static private TreeMap<Long, Node> nodes; // 虛擬節點到真實節點的映射    static private TreeMap<Long, Node> treeKey; //key到真實節點的映射    static private List<Node> shards = new ArrayList<Node>(); // 真實機器節點    private final int NODE_NUM = 100; // 每個機器節點關聯的虛擬節點個數    boolean flag = false;        @SuppressWarnings("static-access")    public Shard(List<Node> shards) {        super();        this.shards = shards;        init();    }    public static void main(String[] args) {        Node s1 = new Node("s1", "192.168.1.1");        Node s2 = new Node("s2", "192.168.1.2");        Node s3 = new Node("s3", "192.168.1.3");        Node s4 = new Node("s4", "192.168.1.4");        shards.add(s1);        shards.add(s2);        shards.add(s3);        shards.add(s4);        Shard<Node> sh = new Shard<Node>(shards);        System.out.println("添加用戶端,一開始有4個主機,分別為s1,s2,s3,s4,每個主機有100個虛擬機器主機:");        sh.keyToNode("101用戶端");        sh.keyToNode("102用戶端");        sh.keyToNode("103用戶端");        sh.keyToNode("104用戶端");        sh.keyToNode("105用戶端");        sh.keyToNode("106用戶端");        sh.keyToNode("107用戶端");        sh.keyToNode("108用戶端");        sh.keyToNode("109用戶端");        sh.deleteS(s4);        sh.addS(s4);        System.out.println("最後的用戶端到主機的映射為:");        printKeyTree();    }            /**     * 列印真實節點的映射     */    public static void printKeyTree(){        for(Iterator<Long> it = treeKey.keySet().iterator();it.hasNext();){            Long lo = it.next();            System.out.println("hash("+lo+")串連到主機->"+treeKey.get(lo));        }    }        /**     * 產生虛擬節點的映射     */    private void init() { // 初始化一致性hash環        nodes = new TreeMap<Long, Node>();        treeKey = new TreeMap<Long, Node>();        for (int i = 0; i != shards.size(); ++i) { // 每個真實機器節點都需要關聯虛擬節點            final Node shardInfo = shards.get(i);            for (int n = 0; n < NODE_NUM; n++)            {                // 一個真實機器節點關聯NODE_NUM個虛擬節點                nodes.put(hash("SHARD-" + shardInfo.name + "-NODE-" + n), shardInfo);            }        }    }    //增加一個主機    private void addS(Node s) {        System.out.println("增加主機"+s+"的變化:");        for (int n = 0; n < NODE_NUM; n++) {            addS(hash("SHARD-" + s.name + "-NODE-" + n), s);        }    }        //添加一個虛擬節點進環形結構,lg為虛擬節點的hash值    public void addS(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, false, lg, true);        }        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+")改變到->"+tail.get(tail.firstKey()));        }    }        //刪除真實節點是s    public void deleteS(Node s){        if(s==null){            return;        }        System.out.println("刪除主機"+s+"的變化:");            for(int i=0;i<NODE_NUM;i++){            //定位s節點的第i的虛擬節點的位置            SortedMap<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);//在s節點的第i個虛擬節點的所有key的集合            }            nodes.remove(tail.firstKey());//從nodes中刪除s節點的第i個虛擬節點            for(Iterator<Long> it = between.keySet().iterator();it.hasNext();){                Long lo = it.next();                if (tail.size() == 0) {                    // 如果是尾節點,則關聯到首接點上                    treeKey.put(lo, nodes.firstEntry().getValue());                    System.out.println("hash("+lo+")改變到->"+nodes.firstEntry().getValue());                } else {                    treeKey.put(lo, tail.get(tail.firstKey()));                    System.out.println("hash("+lo+")改變到->"+tail.get(tail.firstKey()));                }            }        }            }    //映射key到真實節點    public void keyToNode(String key){        Long hashKey = hash(key);        SortedMap<Long, Node> tail = nodes.tailMap(hashKey); // 沿環的順時針找到一個虛擬節點        // 如果是尾節點        if (tail.size() == 0) {            // 映射節點為首節點            treeKey.put(hashKey, nodes.firstEntry().getValue());            System.out.println(key+"(hash: "+hashKey+")串連到主機->"+nodes.firstEntry().getValue());            return;        }        treeKey.put(hashKey, tail.get(tail.firstKey()));        System.out.println(key+"(hash:"+hashKey+")串連到主機->"+tail.get(tail.firstKey()));    }        /**     *  MurMurHash演算法,是非加密HASH演算法,效能很高,     *  比傳統的CRC32,MD5,SHA-1(這兩個演算法都是加密HASH演算法,複雜度本身就很高,帶來的效能上的損害也不可避免)     *  等HASH演算法要快很多,而且據說這個演算法的碰撞率很低.     *  http://murmurhash.googlepages.com/     */    private 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;    }        static class Node{        String name;        String ip;        public Node(String name,String ip) {            this.name = name;            this.ip = ip;        }        @Override        public String toString() {            return this.name+"-"+this.ip;        }    }}

 

java實現hash一致性演算法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.