一致性Hash算法
2021-04-27算法点击王峰 共954字,阅读约需5分钟
算法实现
不带虚拟节点的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| import java.util.SortedMap; import java.util.TreeMap;
public class ConsistentHashingWithoutVirtualNode {
private static String[] servers = {"192.168.0.0:111", "192.168.0.1:111", "192.168.0.2:111", "192.168.0.3:111", "192.168.0.4:111"};
private static SortedMap<Integer, String> sortedMap = new TreeMap<>();
static { for (int i = 0; i < servers.length; i++) { String server = servers[i]; int hash = getHash(server); System.out.println("[" + server + "]加入集合中, 其Hash值为" + hash); sortedMap.put(hash, server); } System.out.println(); }
private static String getServer(String key) { int hash = getHash(key); SortedMap<Integer, String> subMap = sortedMap.tailMap(hash); if (subMap.isEmpty()) { Integer i = sortedMap.firstKey(); return sortedMap.get(i); } else { Integer i = subMap.firstKey(); return subMap.get(i); } }
private static int getHash(String str) { final int p = 16777619; int hash = (int) 2166136261L; for (int i = 0; i < str.length(); i++) hash = (hash ^ str.charAt(i)) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5;
if (hash < 0) hash = Math.abs(hash); return hash; }
public static void main(String[] args) { String[] keys = {"太阳", "月亮", "星星"}; for (String key : keys) System.out.println("[" + key + "]的hash值为" + getHash(key) + ", 被路由到结点[" + getServer(key) + "]"); } }
|
带虚拟节点的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| import java.util.List; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.locks.StampedLock;
public class ConsistentHashingWithVirtualNode { private static final String NODE_SPILT = "@@"; private static final String NODE_PREFIX = "VN";
private final SortedMap<Integer, String> map = new TreeMap<>();
private final List<String> servers;
private final int virtualNodeNum;
private final StampedLock lock = new StampedLock();
public ConsistentHashingWithVirtualNode(List<String> servers, int virtualNodeNum) { this.servers = servers; this.virtualNodeNum = virtualNodeNum; init(); }
private void init() { for (String server : servers) { addServer(server); } }
public void addServer(String server) { long stamp = lock.writeLock(); try { for (int i = 0; i < virtualNodeNum; i++) { String virtual = server + NODE_SPILT + NODE_PREFIX + i; int hash = getHash(virtual); map.put(hash, virtual); } } finally { lock.unlockWrite(stamp); } }
public void removeServer(String server) { long stamp = lock.writeLock(); try { for (int i = 0; i < virtualNodeNum; i++) { String virtual = server + NODE_SPILT + NODE_PREFIX + i; map.remove(getHash(virtual)); } } finally { lock.unlockWrite(stamp); } }
private void removeServer(String server, int i) { long stamp = lock.writeLock(); try { String virtual = server + NODE_SPILT + NODE_PREFIX + i; int hash = getHash(virtual); map.put(hash, virtual); } finally { lock.unlockWrite(stamp); } }
public String findServer(String request) { int hash = getHash(request); long stamp = lock.tryOptimisticRead(); String server = getServerByHashKey(hash); if (!lock.validate(stamp)) { stamp = lock.readLock(); try { server = getServerByHashKey(hash); } finally { lock.unlockRead(stamp); } } return server; }
private String getServerByHashKey(int hash) { SortedMap<Integer, String> subMap = map.tailMap(hash); Integer targetServerKey = subMap.isEmpty() ? map.firstKey() : subMap.firstKey(); String virtual = map.get(targetServerKey); if (virtual != null) { return virtual.split(NODE_SPILT)[0]; } return null; }
private static int getHash(String str) { final int p = 16777619; int hash = (int) 2166136261L; for (int i = 0; i < str.length(); i++) hash = (hash ^ str.charAt(i)) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5;
if (hash < 0) hash = Math.abs(hash); return hash; }
}
|
如果觉得我的文章对您有帮助,请随意打赏。
微信打赏

支付宝打赏
版权声明:本文由 王峰 发表于 王峰的博客转载声明:自由转载-非商用-非衍生-保持署名,非商业转载请注明作者及出处,商业转载请联系作者本人。文章标题:一致性Hash算法文章链接: