【策略】一致性Hash算法(Hash环)的java代码实现
生活随笔
收集整理的這篇文章主要介紹了
【策略】一致性Hash算法(Hash环)的java代码实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【一】一致性hash算法,基本實現分布平衡。
1 package org.ehking.quartz.curator;
2
3 import java.util.SortedMap;
4 import java.util.TreeMap;
5
6 public class ConsistentHashingWithoutVirtualNode {
7 /**
8 * 待添加入Hash環的服務器列表
9 */
10 private static String[] servers = {"192.168.0.0:111", "192.168.0.1:111", "192.168.0.2:111",
11 "192.168.0.3:111", "192.168.0.4:111"};
12
13 /**
14 * key表示服務器的hash值,value表示服務器的名稱
15 */
16 private static SortedMap<Integer, String> sortedMap =
17 new TreeMap<Integer, String>();
18
19 /**
20 * 程序初始化,將所有的服務器放入sortedMap中
21 */
22 static
23 {
24 for (int i = 0; i < servers.length; i++)
25 {
26 int hash = getHash(servers[i]);
27 System.out.println("[" + servers[i] + "]加入集合中, 其Hash值為" + hash);
28 sortedMap.put(hash, servers[i]);
29 }
30 System.out.println();
31 }
32
33 /**
34 * 使用FNV1_32_HASH算法計算服務器的Hash值,這里不使用重寫hashCode的方法,最終效果沒區別
35 */
36 private static int getHash(String str)
37 {
38 final int p = 16777619;
39 int hash = (int)2166136261L;
40 for (int i = 0; i < str.length(); i++)
41 hash = (hash ^ str.charAt(i)) * p;
42 hash += hash << 13;
43 hash ^= hash >> 7;
44 hash += hash << 3;
45 hash ^= hash >> 17;
46 hash += hash << 5;
47
48 // 如果算出來的值為負數則取其絕對值
49 if (hash < 0)
50 hash = Math.abs(hash);
51 return hash;
52 }
53
54 /**
55 * 得到應當路由到的結點
56 */
57 private static String getServer(String node)
58 {
59 // 得到帶路由的結點的Hash值
60 int hash = getHash(node);
61 // 得到大于該Hash值的所有Map
62 SortedMap<Integer, String> subMap =
63 sortedMap.tailMap(hash);
64 // 第一個Key就是順時針過去離node最近的那個結點
65 Integer i = subMap.firstKey();
66 // 返回對應的服務器名稱
67 return subMap.get(i);
68 }
69
70 public static void main(String[] args)
71 {
72 String[] nodes = {"127.0.0.1:1111", "221.226.0.1:2222", "10.211.0.1:3333"};
73 for (int i = 0; i < nodes.length; i++)
74 System.out.println("[" + nodes[i] + "]的hash值為" +
75 getHash(nodes[i]) + ", 被路由到結點[" + getServer(nodes[i]) + "]");
76 }
77 }
View Code
【二】借助虛擬節點,實現分布平衡的hash算法
1 package org.ehking.quartz.curator;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.LinkedList;
6 import java.util.List;
7 import java.util.Set;
8 import java.util.SortedMap;
9 import java.util.TreeMap;
10 import java.util.UUID;
11
12 public class ConsistentHashingWithVirtualNode {
13 /**
14 * 待添加入Hash環的服務器列表
15 */
16 private static String[] servers = { "192.168.0.0:111","192.168.0.1:111", "192.168.0.2:111"};
17
18 /**
19 * 真實結點列表,考慮到服務器上線、下線的場景,即添加、刪除的場景會比較頻繁,這里使用LinkedList會更好
20 */
21 private static List<String> realNodes = new LinkedList<String>();
22 /**
23 * 虛擬節點,key表示虛擬節點的hash值,value表示虛擬節點的名稱
24 */
25 private static SortedMap<Integer, String> virtualNodes =
26 new TreeMap<Integer, String>();
27
28 /**
29 * 虛擬節點的數目,這里寫死,為了演示需要,一個真實結點對應5個虛擬節點
30 */
31 private static final int VIRTUAL_NODES = 1000;
32
33 static
34 {
35 // 先把原始的服務器添加到真實結點列表中
36 for (int i = 0; i < servers.length; i++)
37 realNodes.add(servers[i]);
38
39 // 再添加虛擬節點,遍歷LinkedList使用foreach循環效率會比較高
40 for (String str : realNodes)
41 {
42 for (int i = 0; i < VIRTUAL_NODES; i++)
43 {
44 String virtualNodeName = str + "&&VN" + String.valueOf(i);
45 int hash = getHash(virtualNodeName);
46 System.out.println("虛擬節點[" + virtualNodeName + "]被添加, hash值為" + hash);
47 virtualNodes.put(hash, virtualNodeName);
48 }
49 }
50 System.out.println();
51 }
52
53 /**
54 * 使用FNV1_32_HASH算法計算服務器的Hash值,這里不使用重寫hashCode的方法,最終效果沒區別
55 */
56 private static int getHash(String str)
57 {
58 final int p = 16777619;
59 int hash = (int)2166136261L;
60 for (int i = 0; i < str.length(); i++)
61 hash = (hash ^ str.charAt(i)) * p;
62 hash += hash << 13;
63 hash ^= hash >> 7;
64 hash += hash << 3;
65 hash ^= hash >> 17;
66 hash += hash << 5;
67
68 // 如果算出來的值為負數則取其絕對值
69 if (hash < 0)
70 hash = Math.abs(hash);
71 return hash;
72 }
73
74 /**
75 * 得到應當路由到的結點
76 */
77 private static String getServer(String node)
78 {
79 // 得到帶路由的結點的Hash值
80 int hash = getHash(node);
81 // 得到大于該Hash值的所有Map
82 SortedMap<Integer, String> subMap =
83 virtualNodes.tailMap(hash);
84 Integer i=null;
85 String virtualNode = null;
86 if(subMap==null||subMap.size()==0){
87 i=virtualNodes.firstKey();
88 virtualNode=virtualNodes.get(i);
89 }else{
90 i = subMap.firstKey();
91 virtualNode= subMap.get(i);
92 }
93 // 第一個Key就是順時針過去離node最近的那個結點
94
95 // 返回對應的虛擬節點名稱,這里字符串稍微截取一下
96 return virtualNode.substring(0, virtualNode.indexOf("&&"));
97 }
98
99 public static void main(String[] args)
100 {
101
102 HashMap<String,Integer> map=new HashMap<String, Integer>();
103 List<String> id=new ArrayList<String>();
104 for(int i=0;i<1000;i++){
105 id.add(UUID.randomUUID().toString().replace("-", ""));
106 //id.add("adasfdsafdsgfdsagdsafdsafdsaf"+i);
107 }
108 for (int i = 0; i < id.size(); i++){
109 String aString=getServer(id.get(i));
110 Integer aInteger=map.get(aString);
111 if(aInteger==null){
112 map.put(aString,1);
113 }else{
114 map.put(aString, aInteger+1);
115 }
116 }
117 Set<String> set= map.keySet();
118 for(String a:set){
119 System.out.println("節點【"+a+"】分配到元素個數為==>"+map.get(a));
120 }
121 }
122 }
View Code
總結
以上是生活随笔為你收集整理的【策略】一致性Hash算法(Hash环)的java代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: flash怎么制作一种可以转动的绚丽花环
- 下一篇: Flash如何制作一个跟随鼠标感应放大缩