作者 crossoverJie

:sparkles: Introducing new features.两种一致性hash 算法

@@ -21,7 +21,7 @@ public class SortArrayMap { @@ -21,7 +21,7 @@ public class SortArrayMap {
21 buckets = new Node[DEFAULT_SIZE]; 21 buckets = new Node[DEFAULT_SIZE];
22 } 22 }
23 23
24 - public void add(int key, String value) { 24 + public void add(Long key, String value) {
25 checkSize(size + 1); 25 checkSize(size + 1);
26 Node node = new Node(key, value); 26 Node node = new Node(key, value);
27 buckets[size++] = node; 27 buckets[size++] = node;
@@ -36,7 +36,7 @@ public class SortArrayMap { @@ -36,7 +36,7 @@ public class SortArrayMap {
36 } 36 }
37 } 37 }
38 38
39 - public String firstNodeValue(int key) { 39 + public String firstNodeValue(long key) {
40 if (size == 0){ 40 if (size == 0){
41 return null ; 41 return null ;
42 } 42 }
@@ -86,10 +86,10 @@ public class SortArrayMap { @@ -86,10 +86,10 @@ public class SortArrayMap {
86 * 数据节点 86 * 数据节点
87 */ 87 */
88 private class Node { 88 private class Node {
89 - public int key; 89 + public Long key;
90 public String value; 90 public String value;
91 91
92 - public Node(int key, String value) { 92 + public Node(Long key, String value) {
93 this.key = key; 93 this.key = key;
94 this.value = value; 94 this.value = value;
95 } 95 }
  1 +package com.crossoverjie.cim.common.route.algorithm;
  2 +
  3 +/**
  4 + * Function:
  5 + *
  6 + * @author crossoverJie
  7 + * Date: 2019-02-27 00:31
  8 + * @since JDK 1.8
  9 + */
  10 +public interface RouteHandle {
  11 +
  12 + String selectServer() ;
  13 +}
  1 +package com.crossoverjie.cim.common.route.algorithm.consistenthash;
  2 +
  3 +import java.io.UnsupportedEncodingException;
  4 +import java.security.MessageDigest;
  5 +import java.security.NoSuchAlgorithmException;
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * Function:
  10 + *
  11 + * @author crossoverJie
  12 + * Date: 2019-02-27 00:35
  13 + * @since JDK 1.8
  14 + */
  15 +public abstract class AbstractConsistentHash {
  16 +
  17 + protected void add(long key,String value){}
  18 +
  19 + protected void sort(){}
  20 +
  21 + /**
  22 + * 根据当前的
  23 + * @param value
  24 + * @return
  25 + */
  26 + protected String getFirstNodeValue(String value){
  27 + return null ;
  28 + }
  29 +
  30 + public void process(List<String> values){
  31 + for (String value : values) {
  32 + add(hash(value), value);
  33 + }
  34 + sort();
  35 + }
  36 +
  37 + /**
  38 + * hash 运算
  39 + * @param value
  40 + * @return
  41 + */
  42 + public Long hash(String value){
  43 + MessageDigest md5;
  44 + try {
  45 + md5 = MessageDigest.getInstance("MD5");
  46 + } catch (NoSuchAlgorithmException e) {
  47 + throw new RuntimeException("MD5 not supported", e);
  48 + }
  49 + md5.reset();
  50 + byte[] keyBytes = null;
  51 + try {
  52 + keyBytes = value.getBytes("UTF-8");
  53 + } catch (UnsupportedEncodingException e) {
  54 + throw new RuntimeException("Unknown string :" + value, e);
  55 + }
  56 +
  57 + md5.update(keyBytes);
  58 + byte[] digest = md5.digest();
  59 +
  60 + // hash code, Truncate to 32-bits
  61 + long hashCode = ((long) (digest[3] & 0xFF) << 24)
  62 + | ((long) (digest[2] & 0xFF) << 16)
  63 + | ((long) (digest[1] & 0xFF) << 8)
  64 + | (digest[0] & 0xFF);
  65 +
  66 + long truncateHashCode = hashCode & 0xffffffffL;
  67 + return truncateHashCode;
  68 + }
  69 +}
  1 +package com.crossoverjie.cim.common.route.algorithm.consistenthash;
  2 +
  3 +import com.crossoverjie.cim.common.route.algorithm.RouteHandle;
  4 +
  5 +/**
  6 + * Function:
  7 + *
  8 + * @author crossoverJie
  9 + * Date: 2019-02-27 00:33
  10 + * @since JDK 1.8
  11 + */
  12 +public class ConsistentHashHandle implements RouteHandle {
  13 +
  14 +
  15 +
  16 +
  17 + @Override
  18 + public String selectServer() {
  19 + return null;
  20 + }
  21 +}
  1 +package com.crossoverjie.cim.common.route.algorithm.consistenthash;
  2 +
  3 +import com.crossoverjie.cim.common.data.construct.SortArrayMap;
  4 +
  5 +/**
  6 + * Function:
  7 + *
  8 + * @author crossoverJie
  9 + * Date: 2019-02-27 00:38
  10 + * @since JDK 1.8
  11 + */
  12 +public class SortArrayMapConsistentHash extends AbstractConsistentHash {
  13 +
  14 + private SortArrayMap sortArrayMap = new SortArrayMap();
  15 +
  16 + @Override
  17 + protected void add(long key, String value) {
  18 + sortArrayMap.add(key, value);
  19 + }
  20 +
  21 + @Override
  22 + protected void sort() {
  23 + sortArrayMap.sort();
  24 + sortArrayMap.print();
  25 + }
  26 +
  27 + @Override
  28 + protected String getFirstNodeValue(String value) {
  29 + long hash = super.hash(value);
  30 + System.out.println("value=" + value + " hash = " + hash);
  31 + return sortArrayMap.firstNodeValue(hash);
  32 + }
  33 +
  34 +}
  1 +package com.crossoverjie.cim.common.route.algorithm.consistenthash;
  2 +
  3 +import java.util.SortedMap;
  4 +import java.util.TreeMap;
  5 +
  6 +/**
  7 + * Function:
  8 + *
  9 + * @author crossoverJie
  10 + * Date: 2019-02-27 01:16
  11 + * @since JDK 1.8
  12 + */
  13 +public class TreeMapConsistentHash extends AbstractConsistentHash {
  14 + private TreeMap<Long,String> treeMap = new TreeMap<Long, String>() ;
  15 +
  16 + @Override
  17 + protected void add(long key, String value) {
  18 + treeMap.put(key, value);
  19 + }
  20 +
  21 + @Override
  22 + protected void sort() {
  23 + }
  24 +
  25 + @Override
  26 + protected String getFirstNodeValue(String value) {
  27 + long hash = super.hash(value);
  28 + System.out.println("value=" + value + " hash = " + hash);
  29 + SortedMap<Long, String> last = treeMap.tailMap(hash);
  30 + if (!last.isEmpty()) {
  31 + return last.get(last.firstKey());
  32 + }
  33 + return treeMap.firstEntry().getValue();
  34 + }
  35 +}
@@ -8,7 +8,7 @@ public class SortArrayMapTest { @@ -8,7 +8,7 @@ public class SortArrayMapTest {
8 public void ad() { 8 public void ad() {
9 SortArrayMap map = new SortArrayMap() ; 9 SortArrayMap map = new SortArrayMap() ;
10 for (int i = 0; i < 9; i++) { 10 for (int i = 0; i < 9; i++) {
11 - map.add(i ,"127.0.0." + i); 11 + map.add(Long.valueOf(i) ,"127.0.0." + i);
12 } 12 }
13 map.print(); 13 map.print();
14 System.out.println(map.size()); 14 System.out.println(map.size());
@@ -18,7 +18,7 @@ public class SortArrayMapTest { @@ -18,7 +18,7 @@ public class SortArrayMapTest {
18 public void add() { 18 public void add() {
19 SortArrayMap map = new SortArrayMap() ; 19 SortArrayMap map = new SortArrayMap() ;
20 for (int i = 0; i < 10; i++) { 20 for (int i = 0; i < 10; i++) {
21 - map.add(i ,"127.0.0." + i); 21 + map.add(Long.valueOf(i) ,"127.0.0." + i);
22 } 22 }
23 map.print(); 23 map.print();
24 System.out.println(map.size()); 24 System.out.println(map.size());
@@ -28,7 +28,7 @@ public class SortArrayMapTest { @@ -28,7 +28,7 @@ public class SortArrayMapTest {
28 public void add2() { 28 public void add2() {
29 SortArrayMap map = new SortArrayMap() ; 29 SortArrayMap map = new SortArrayMap() ;
30 for (int i = 0; i < 20; i++) { 30 for (int i = 0; i < 20; i++) {
31 - map.add(i ,"127.0.0." + i); 31 + map.add(Long.valueOf(i) ,"127.0.0." + i);
32 } 32 }
33 map.sort(); 33 map.sort();
34 map.print(); 34 map.print();
@@ -39,10 +39,10 @@ public class SortArrayMapTest { @@ -39,10 +39,10 @@ public class SortArrayMapTest {
39 public void add3() { 39 public void add3() {
40 SortArrayMap map = new SortArrayMap() ; 40 SortArrayMap map = new SortArrayMap() ;
41 41
42 - map.add(100,"127.0.0.100");  
43 - map.add(10,"127.0.0.10");  
44 - map.add(8,"127.0.0.8");  
45 - map.add(1000,"127.0.0.1000"); 42 + map.add(100L,"127.0.0.100");
  43 + map.add(10L,"127.0.0.10");
  44 + map.add(8L,"127.0.0.8");
  45 + map.add(1000L,"127.0.0.1000");
46 46
47 map.print(); 47 map.print();
48 System.out.println(map.size()); 48 System.out.println(map.size());
@@ -52,10 +52,10 @@ public class SortArrayMapTest { @@ -52,10 +52,10 @@ public class SortArrayMapTest {
52 public void firstNode() { 52 public void firstNode() {
53 SortArrayMap map = new SortArrayMap() ; 53 SortArrayMap map = new SortArrayMap() ;
54 54
55 - map.add(100,"127.0.0.100");  
56 - map.add(10,"127.0.0.10");  
57 - map.add(8,"127.0.0.8");  
58 - map.add(1000,"127.0.0.1000"); 55 + map.add(100L,"127.0.0.100");
  56 + map.add(10L,"127.0.0.10");
  57 + map.add(8L,"127.0.0.8");
  58 + map.add(1000L,"127.0.0.1000");
59 59
60 map.sort(); 60 map.sort();
61 map.print(); 61 map.print();
@@ -66,10 +66,10 @@ public class SortArrayMapTest { @@ -66,10 +66,10 @@ public class SortArrayMapTest {
66 public void firstNode2() { 66 public void firstNode2() {
67 SortArrayMap map = new SortArrayMap() ; 67 SortArrayMap map = new SortArrayMap() ;
68 68
69 - map.add(100,"127.0.0.100");  
70 - map.add(10,"127.0.0.10");  
71 - map.add(8,"127.0.0.8");  
72 - map.add(1000,"127.0.0.1000"); 69 + map.add(100L,"127.0.0.100");
  70 + map.add(10L,"127.0.0.10");
  71 + map.add(8L,"127.0.0.8");
  72 + map.add(1000L,"127.0.0.1000");
73 73
74 map.sort(); 74 map.sort();
75 map.print(); 75 map.print();
@@ -80,10 +80,10 @@ public class SortArrayMapTest { @@ -80,10 +80,10 @@ public class SortArrayMapTest {
80 public void firstNode3() { 80 public void firstNode3() {
81 SortArrayMap map = new SortArrayMap() ; 81 SortArrayMap map = new SortArrayMap() ;
82 82
83 - map.add(100,"127.0.0.100");  
84 - map.add(10,"127.0.0.10");  
85 - map.add(8,"127.0.0.8");  
86 - map.add(1000,"127.0.0.1000"); 83 + map.add(100L,"127.0.0.100");
  84 + map.add(10L,"127.0.0.10");
  85 + map.add(8L,"127.0.0.8");
  86 + map.add(1000L,"127.0.0.1000");
87 87
88 map.sort(); 88 map.sort();
89 map.print(); 89 map.print();
@@ -94,10 +94,10 @@ public class SortArrayMapTest { @@ -94,10 +94,10 @@ public class SortArrayMapTest {
94 public void firstNode4() { 94 public void firstNode4() {
95 SortArrayMap map = new SortArrayMap() ; 95 SortArrayMap map = new SortArrayMap() ;
96 96
97 - map.add(100,"127.0.0.100");  
98 - map.add(10,"127.0.0.10");  
99 - map.add(8,"127.0.0.8");  
100 - map.add(1000,"127.0.0.1000"); 97 + map.add(100L,"127.0.0.100");
  98 + map.add(10L,"127.0.0.10");
  99 + map.add(8L,"127.0.0.8");
  100 + map.add(1000L,"127.0.0.1000");
101 101
102 map.sort(); 102 map.sort();
103 map.print(); 103 map.print();
@@ -109,10 +109,10 @@ public class SortArrayMapTest { @@ -109,10 +109,10 @@ public class SortArrayMapTest {
109 public void add4() { 109 public void add4() {
110 SortArrayMap map = new SortArrayMap() ; 110 SortArrayMap map = new SortArrayMap() ;
111 111
112 - map.add(100,"127.0.0.100");  
113 - map.add(10,"127.0.0.10");  
114 - map.add(8,"127.0.0.8");  
115 - map.add(1000,"127.0.0.1000"); 112 + map.add(100L,"127.0.0.100");
  113 + map.add(10L,"127.0.0.10");
  114 + map.add(8L,"127.0.0.8");
  115 + map.add(1000L,"127.0.0.1000");
116 116
117 map.sort(); 117 map.sort();
118 map.print(); 118 map.print();
@@ -129,7 +129,7 @@ public class SortArrayMapTest { @@ -129,7 +129,7 @@ public class SortArrayMapTest {
129 for (int i = 0; i < count; i++) { 129 for (int i = 0; i < count; i++) {
130 double d = Math.random(); 130 double d = Math.random();
131 int ran = (int)(d*100); 131 int ran = (int)(d*100);
132 - map.add(i + ran ,"127.0.0." + i); 132 + map.add(Long.valueOf(i + ran) ,"127.0.0." + i);
133 } 133 }
134 map.sort(); 134 map.sort();
135 long end = System.currentTimeMillis() ; 135 long end = System.currentTimeMillis() ;
@@ -148,7 +148,7 @@ public class SortArrayMapTest { @@ -148,7 +148,7 @@ public class SortArrayMapTest {
148 for (int i = 0; i < count; i++) { 148 for (int i = 0; i < count; i++) {
149 double d = Math.random(); 149 double d = Math.random();
150 int ran = (int)(d*100); 150 int ran = (int)(d*100);
151 - map.add(i + ran ,"127.0.0." + i); 151 + map.add(Long.valueOf(i + ran) ,"127.0.0." + i);
152 } 152 }
153 long end = System.currentTimeMillis() ; 153 long end = System.currentTimeMillis() ;
154 System.out.println("不排耗时 " + (end -star)); 154 System.out.println("不排耗时 " + (end -star));
  1 +package com.crossoverjie.cim.common.route.algorithm.consistenthash;
  2 +
  3 +import org.junit.Test;
  4 +
  5 +import java.util.ArrayList;
  6 +import java.util.List;
  7 +
  8 +import static org.junit.Assert.*;
  9 +
  10 +public class SortArrayMapConsistentHashTest {
  11 +
  12 + @Test
  13 + public void getFirstNodeValue() {
  14 + AbstractConsistentHash map = new SortArrayMapConsistentHash() ;
  15 +
  16 + List<String> strings = new ArrayList<String>();
  17 + for (int i = 0; i < 10; i++) {
  18 + strings.add("127.0.0." + i) ;
  19 + }
  20 + map.process(strings);
  21 +
  22 + String firstNodeValue = map.getFirstNodeValue("zhangsan");
  23 + System.out.println(firstNodeValue);
  24 + }
  25 +
  26 + @Test
  27 + public void getFirstNodeValue2() {
  28 + AbstractConsistentHash map = new SortArrayMapConsistentHash() ;
  29 +
  30 + List<String> strings = new ArrayList<String>();
  31 + for (int i = 0; i < 10; i++) {
  32 + strings.add("127.0.0." + i) ;
  33 + }
  34 + map.process(strings);
  35 +
  36 + String firstNodeValue = map.getFirstNodeValue("zhangsan2");
  37 + System.out.println(firstNodeValue);
  38 + }
  39 +}
  1 +package com.crossoverjie.cim.common.route.algorithm.consistenthash;
  2 +
  3 +import org.junit.Test;
  4 +
  5 +import java.util.ArrayList;
  6 +import java.util.List;
  7 +
  8 +public class TreeMapConsistentHashTest {
  9 +
  10 + @Test
  11 + public void getFirstNodeValue() {
  12 + AbstractConsistentHash map = new TreeMapConsistentHash() ;
  13 +
  14 + List<String> strings = new ArrayList<String>();
  15 + for (int i = 0; i < 10; i++) {
  16 + strings.add("127.0.0." + i) ;
  17 + }
  18 + map.process(strings);
  19 +
  20 + String firstNodeValue = map.getFirstNodeValue("zhangsan");
  21 + System.out.println(firstNodeValue);
  22 + }
  23 +
  24 +
  25 +
  26 + @Test
  27 + public void getFirstNodeValue2() {
  28 + AbstractConsistentHash map = new TreeMapConsistentHash() ;
  29 +
  30 + List<String> strings = new ArrayList<String>();
  31 + for (int i = 0; i < 10; i++) {
  32 + strings.add("127.0.0." + i) ;
  33 + }
  34 + map.process(strings);
  35 +
  36 + String firstNodeValue = map.getFirstNodeValue("zhangsan2");
  37 + System.out.println(firstNodeValue);
  38 + }
  39 +}