1 /**

2 * 一致性hash 的java 实现3 *@authorluoqiang4 * @data 2016/11/085 */

6 public classConsistencyHash {7

8 public ConsistencyHash(Listshards){9 shards =shards;10 init();11 }12

13 private static classNode{14 privateString name;15 privateString ip;16

17 publicNode(String name, String ip) {18 this.name =name;19 this.ip =ip;20 }21

22 publicString getName() {23 returnname;24 }25

26 public voidsetName(String name) {27 this.name =name;28 }29

30 publicString getIp() {31 returnip;32 }33

34 public voidsetIp(String ip) {35 this.ip =ip;36 }37

38 @Override39 publicString toString() {40 return "Node{" +

41 "ip='" + ip + '\'' +

42 ", name='" + name + '\'' +

43 '}';44 }45 }46

47 private static classClient{48 publicClient(String name, Long hashCode) {49 this.name =name;50 this.hashCode =hashCode;51 }52

53 publicClient(String name) {54 this.name =name;55 }56

57 privateString name;58 privateLong hashCode;59

60 publicString getName() {61 returnname;62 }63

64 public voidsetName(String name) {65 this.name =name;66 }67

68 publicLong getHashCode() {69 returnhashCode;70 }71

72 public voidsetHashCode(Long hashCode) {73 this.hashCode =hashCode;74 }75 }76

77 private static TreeMap nodes;//虚拟节点hash值 到 真实主机 的映射

78

79 private static TreeMap treeKey;//客户端hash值 到 真实节点 的映射

80

81 private static List shards = new ArrayList();//真实主机

82

83 private static List cliends = new ArrayList();//客户端

84

85 private static TreeMap clientTree;//客户端自己hash 和客户端的映射

86

87 private static final int NODE_NUM = 100;//每个机器节点关联的虚拟节点个数

88

89

90 private voidinit(){91 nodes = new TreeMap();92 treeKey = new TreeMap();93 clientTree = new TreeMap();94 for (int i = 0; i < shards.size(); i++) {95 final Node shardInfo =shards.get(i);96 for (int n = 0; n < NODE_NUM; n++) {97 Long key = hash("SHARD-"+shardInfo.name+"-NODE-"+n);98 nodes.put(key,shardInfo);99 }100 }101 }102

103 /**

104 * 添加一个真实主机105 */

106 private voidaddNode(Node n){107 System.out.println("添加主机"+n+"的变化:");108 for (int i = 0; i < NODE_NUM; i++) {109 Long lg = hash("SHARD-"+n.name+"-NODE-"+i);110 SortedMap head =nodes.headMap(lg);111 SortedMapbetween;112 if(head.size() == 0){113 between = treeKey.tailMap(nodes.lastKey());//建立在 最后一个虚拟主机的hash值 不和 客户端的hash值相等。

114 }else{115 Long begin =head.lastKey();116 between =treeKey.subMap(begin,lg);117 }118 nodes.put(lg,n);119 for(Iterator it=between.keySet().iterator();it.hasNext();){120 Long lo =it.next();121 treeKey.put(lo, nodes.get(lg));122 }123 }124 }125

126 /**

127 * 删除一个真实主机128 *@paramn129 */

130 private voiddeleteNode(Node n){131 System.out.println("删除主机"+n+"的变化:");132 for (int i = 0; i < NODE_NUM; i++) {133 Long virturalHashCode = hash("SHARD-" + n.name + "-NODE-" +i);134 SortedMap tail = nodes.tailMap(virturalHashCode);//等于和大于 此值 == 顺时针 环形此值后面

135 SortedMap head = nodes.headMap(virturalHashCode);//严格小于 此值(不等于) == 顺时针 环形此值前面

136 SortedMapbetween;137 if(head.size() == 0){138 between =treeKey.tailMap(nodes.lastKey());139 }else{140 Long begin =head.lastKey();141 Long end =tail.firstKey();142 /**

143 * 方法用于返回此映射的键值从fromKey(包括)到toKey(不包括)的部分视图。144 * (如果fromKey和toKey相等,则返回映射为空)返回的映射受此映射支持,145 * 因此改变返回映射反映在此映射中,反之亦然。146 */

147 between = treeKey.subMap(begin,end);//在n节点的第i个虚拟节点的所有key的集合

148 }149 nodes.remove(virturalHashCode);//从nodes中删除n节点的第i个虚拟节点

150 for(Iterator it =between.keySet().iterator();it.hasNext();){151 Long lo =it.next();152 treeKey.put(lo, nodes.get(tail.firstKey()));153 }154 }155 }156

157 /**

158 * 客户端hash值 映射 到 真实主机159 */

160 private void keyToNode(Listclients){161 for(Client client : clients) {162 Long hashCode =hash(client.getName());163 SortedMap tail = nodes.tailMap(hashCode); //沿环的顺时针找到一个虚拟节点

164 Node node = tail.size() == 0 ?nodes.get(nodes.firstKey()) : nodes.get(tail.firstKey());165 treeKey.put(hashCode,node);166 client.setHashCode(hashCode);167 clientTree.put(hashCode,client);168 }169 }170

171 /**

172 * 输出客户端 映射到 真实主机173 */

174 private voidprintKeyTree(){175 for(Iterator it =treeKey.keySet().iterator();it.hasNext();){176 Long lo =it.next();177 System.out.println(clientTree.get(lo).name+"(hash:"+lo+")连接到主机->"+treeKey.get(lo));178 }179 }180

181 /**

182 * MurMurHash算法,是非加密HASH算法,性能很高,183 * 比传统的CRC32,MD5,SHA-1184 * (这两个算法都是加密HASH算法,复杂度本身就很高,带来的性能上的损害也不可避免)185 * 等HASH算法要快很多,而且据说这个算法的碰撞率很低.186 *http://murmurhash.googlepages.com/

187 */

188 privateLong hash(String key){189

190 ByteBuffer buf =ByteBuffer.wrap(key.getBytes());191 int seed = 0x1234ABCD;192

193 ByteOrder byteOrder =buf.order();194 buf.order(ByteOrder.LITTLE_ENDIAN);195

196 long m = 0xc6a4a7935bd1e995L;197 int r = 47;198

199 long h = seed ^ (buf.remaining() *m);200

201 longk;202 while (buf.remaining() >= 8) {203 k =buf.getLong();204

205 k *=m;206 k ^= k >>>r;207 k *=m;208

209 h ^=k;210 h *=m;211 }212

213 if (buf.remaining() > 0) {214 ByteBuffer finish = ByteBuffer.allocate(8).order(215 ByteOrder.LITTLE_ENDIAN);216 //for big-endian version, do this first:217 //finish.position(8-buf.remaining());

218 finish.put(buf).rewind();219 h ^=finish.getLong();220 h *=m;221 }222

223 h ^= h >>>r;224 h *=m;225 h ^= h >>>r;226

227 buf.order(byteOrder);228 returnh;229 }230

231

232 public static voidmain(String[] args) {233 /**

234 * 客户端的hash值 和 真实主机的100个虚拟节点的hash值235 *236 * 一起均匀地分布在顺时针由小到大这个环上。(0 - 2^32 )237 *238 * 具体 客户端 最终 连接到 哪个主机,239 *240 * 原则是:将客户端hash值,顺时针往后 最近的 虚拟节点hash值。241 *242 */

243 Node s1 = new Node("s1", "192.168.1.1");244 Node s2 = new Node("s2", "192.168.1.2");245 Node s3 = new Node("s3", "192.168.1.3");246 Node s4 = new Node("s4", "192.168.1.4");247 Node s5 = new Node("s5", "192.168.1.5");248 shards.add(s1);249 shards.add(s2);250 shards.add(s3);251 shards.add(s4);252 ConsistencyHash sh = newConsistencyHash(shards);253 System.out.println("添加客户端,一开始有4个主机,分别为s1,s2,s3,s4,每个主机有100个虚拟主机:");254 for (int i = 1; i <= 9; i++) {255 String name = "10"+i+"客户端";256 cliends.add(newClient(name));257 }258 sh.keyToNode(cliends);259 sh.printKeyTree();260 sh.deleteNode(s2);261 sh.printKeyTree();262 sh.addNode(s5);263 sh.printKeyTree();264 }265 }

java 一致性hash算法 均衡分发_负载均衡-基础-一致性哈希算法及java实现相关推荐

  1. 一致性 Hash 是什么?在负载均衡中的应用

    点击上方"服务端思维",选择"设为星标" 回复"669"获取独家整理的精选资料集 回复"加群"加入全国服务端高端社群「后 ...

  2. 负载均衡策略_负载均衡策略

    负载均衡策略有哪些?在实际应用中,我们可能不想仅仅是把客户端的服务请求平均地分配给内部服务器,而不管服务器是否宕机.而是想使Pentium III服务器比Pentium II能接受更多的服务请求,一台 ...

  3. php负载均衡原理_负载均衡的原理(通俗理解)

    简单的来说, 假设,你在放洗脚水,并且,当前你只有一洗脚盆.那么,你的洗脚水不管有多少,你最多就能装一个洗脚盆的 这个就是,单服务器应用场景,你的流量就是洗脚水, 然后,你娶了一个媳妇, 这个时候,你 ...

  4. grpc系列:负载均衡及grpc负载均衡相关整理

    一.负载均衡 负载均衡(LB)在微服务架构演进中具有非常重要的意义,负载均衡是高可用网络基础架构的关键组件,我们的期望是调用是平均分配在所有的服务器服务器上的,通常用于将工作负载分布到多个服务器来提高 ...

  5. 详解【负载均衡】(负载均衡算法、一致性hash、负载均衡架构分析)

    作者:duktig 博客:https://duktig.cn 优秀还努力.愿你付出甘之如饴,所得归于欢喜. 本文源码参看:https://github.com/duktig666/distribute ...

  6. 负载均衡的几种方式_负载均衡的几种方式

    负载均衡其实就是任务的分发,使得任务能按照你的预想分配到各个计算单元上,它能提高服务对外的性能,避免单点失效场景.这里要注意的一点是虽说叫负载均衡,但是有时候我们的分配算法就是不是均衡的. 比如配个n ...

  7. 服务器负载不高 响应慢_负载均衡有哪几大类别?

    我们在将工作分配给所有的实际服务器时,因为每台服务器的承载能力各不相同,也可能因为某台服务器身兼多职,导致某些服务器过载,服务器响应速度越来越慢.那么如何解决这个问题呢?这个时候,负载均衡就应运而生了 ...

  8. mysql 硬负载_软负载均衡和硬负载均衡

    一.负载均衡 负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性. 负载均衡,英文名称为 Load ...

  9. 负载均衡 一直跑一个服务器_终于把服务器负载均衡和客户端负载均衡讲清楚了...

    服务端负载均衡 我们常说的负载均衡都是指服务端负载均衡,服务端负载均衡又分为硬件负载均衡,软件负载均衡. 硬件负载均衡主要是在各服务器节点 前加上负载均衡的设备,如F5 软件负载均衡主要指的是在服务器 ...

最新文章

  1. hbase shell-namespace(命名空间指令)
  2. window7 ubuntu12.04 Opensuse13.04 三系统安装
  3. 《游戏编程入门 4th》笔记(2 / 14):监听Windows消息
  4. Protocol Buffer技术详解(C++实例)
  5. C语言解力扣461.汉明距离
  6. arcgis中python计算面积的表达式_解析ArcGis的字段计算器(一)——数值型数据计算,从“面积计算”开始...
  7. ipv6有必要打开吗_路由器中的IPv6功能需不需要开启?
  8. 常用技术网站2017-2018
  9. 一文搞懂MySQL索引所有知识点(建议收藏)
  10. conda管理python开发环境
  11. Google Chrome崩溃图片
  12. 【Error】初始化ant design pro项目时遇到“pro 不是内部或外部命令”
  13. 数据结构中遍历的意义
  14. 搭建WIKI-dokuwiki
  15. 如何使用windebug追踪ASL CODE
  16. Win10间歇性卡顿
  17. English Learning - Day48 作业打卡 2023.2.2 周四
  18. 智能家居助手详细设计与实现
  19. 搭建自己的网站(入门到入狱)
  20. MFC:将工程从VC6.0工程升级到VS2017所遇到的代码不兼容问题集合

热门文章

  1. Eclipse启动慢解决方案
  2. Eclipse启动慢,运行也慢
  3. Oracle获取当前毫秒级时间
  4. JavaScript-初识ajax、ajax封装、及json对象使用(上)
  5. hive sql 修改列名
  6. css+css3层叠样式表标签汇总(笔记)
  7. FreePBX 命令一览
  8. 谈宇宙尽头及维度空间的关系
  9. 爱陆通工业级路由器与智能制造的适配度up!
  10. 分销管理软件到底能给经营者带来什么?