网站为了支撑更大的用户访问量,往往需要对用户访问的数据做cache,对于访问量特别大的门户网站,一般都提供专门的cache服务机群和负载均衡来专门处理缓存,负载均衡的算法很多,轮循算法、哈希算法、最少连接算法、响应速度算法等,hash算法是比较常用的一种,它的常用思想是先计算出一个hash值,然后使用 CRC余数算法将hash值和机器数mod后取余数,机器的编号可以是0到N-1(N是机器数),计算出的结果一一对应即可。

我们知道缓存最关键的就是命中率这个因素,如果命中率非常低,那么缓存也就失去了它的意义,因此实际生产环境中我们的一个重要目标就是提高缓存命中率。如上所述,采用一般的CRC取余的hash算法虽然能达到负载均衡的目的,但是它存在一个严重的问题,那就是如果我们其中一台服务器down掉,那么我们就需要在计算缓存过程中将这台服务器去掉,即N台服务器,目前就只有N-1台提供缓存服务,此时需要一个rehash过程,而reash得到的结果将导致正常的用户请求不能找到原来缓存数据的正确机器,其他N-1台服务器上的缓存数据将大量失效,此时所有的用户请求全部会集中到数据库上,严重可能导致整个生产环境挂掉.

举个例子,有5台服务器,他们编号分别是0(A),1(B),2(C),3(D),4(E)  ,正常情况下,假设用户数据hash值为12,那么对应的数据应该缓存在12%5=2号服务器上,假设编号为3的服务器此时挂掉,那么将其移除后就得到一个新的0(A),1(B),2(C),3(E)(注:这里的编号3其实就是原来的4号服务器)服务器列表,此时用户来取数据,同样hash值为12,rehash后的得到的机器编号12%4=0号服务器,可见,此时用户到0号服务器去找数据明显就找不到,出现了cache不命中现象,如果不命中此时应用会从后台数据库重新读取数据再cache到0号服务器上,如果大量用户出现这种情况,那么后果不堪设想。同样,增加一台缓存服务器,也会导致同样的后果,感兴趣的读者可以自行推敲。

可以有一种设想,要提高命中率就得减少增加或者移除服务器rehash带来的影响,那么有这样一种算法么?Consistent hashing算法就是这样一种hash算法,它的算法思想是:首先求出服务器(节点)的哈希值,并将其配置到0~2^32的圆上。然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过2^32仍然找不到服务器,就会保存到第一台服务器上。下面有一张比较经典的图,直接用过来,不修改了。

图一  Consistent Hashing原理示意图

这里有四台服务器,我们假设增加一台服务器Node5,可以看到,它影响的数据只是在增加Node5逆时针方向的数据会受到影响。同样,删除其中一台服务器,例如删除服务器node4,那么影响的数据也只是node4上缓存的数据。

图二 Consistent Hashing添加服务器

Consistent Hashing最大限度地抑制了hash键的重新分布。另外要取得比较好的负载均衡的效果,往往在服务器数量比较少的时候需要增加虚拟节点来保证服务器能均匀的分布在圆环上。因为使用一般的hash方法,服务器的映射地点的分布非常不均匀。使用虚拟节点的思想,为每个物理节点(服务器)在圆上分配100~200个点。这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布。用户数据映射在虚拟节点上,就表示用户数据真正存储位置是在该虚拟节点代表的实际物理服务器上。
下面有一个图描述了需要为每台物理服务器增加的虚拟节点。

图三 虚拟节点倍数- 物理节点数关系图

x轴表示的是需要为每台物理服务器扩展的虚拟节点倍数(scale),y轴是实际物理服务器数,可以看出,当物理服务器的数量很小时,需要更大的虚拟节点,反之则需要更少的节点,从图上可以看出,在物理服务器有10台时,差不多需要为每台服务器增加100~200个虚拟节点才能达到真正的负载均衡。

下面是一个简单的java参考实现:

import java.util.Collection; import java.util.SortedMap; import java.util.TreeMap; public class ConsistentHash<T> { private final HashFunction hashFunction; private final int numberOfReplicas; private final SortedMap<Integer, T> circle = new TreeMap<Integer, T>(); public ConsistentHash( HashFunction hashFunction, //hash算法 int numberOfReplicas,//虚拟节点数 Collection<T> nodes//物理节点 ) { this.hashFunction = hashFunction; this.numberOfReplicas = numberOfReplicas; for (T node : nodes) { add(node); } } public void add(T node) { for (int i = 0; i < numberOfReplicas; i++) { circle.put(hashFunction.hash(node.toString() + i), node); } } public void remove(T node) { for (int i = 0; i < numberOfReplicas; i++) { circle.remove(hashFunction.hash(node.toString() + i)); } } //关键算法 public T get(Object key) { if (circle.isEmpty()) { return null; } int hash = hashFunction.hash(key); if (!circle.containsKey(hash)) { SortedMap<Integer, T> tailMap = circle.tailMap(hash); hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); } return circle.get(hash); } }

转载于:https://www.cnblogs.com/lovingprince/archive/2009/10/09/2166302.html

Consistent hashing相关推荐

  1. 一致性 hash 算法( consistent hashing )

    原文地址:http://blog.csdn.net/sparkliang/article/details/5279393 consistent hashing 算法早在 1997 年就在论文 Cons ...

  2. 一致性哈希(Consistent Hashing)

    在大型web应用中,缓存可算是当今的一个标准开发配置了.在大规模的缓存应用中,应运而生了分布式缓存系统.分布式缓存系统的基本原理,大家也有所耳闻.key-value如何均匀的分散到集群中?说到此,最常 ...

  3. 一致性hash算法 - consistent hashing

    参考: http://yacare.iteye.com/blog/1973022 1.   情景分析 前一篇博文分析了HashMap源码,HashMap在许多场景中作为存储数据的不二选择. 但是否使用 ...

  4. 转载:一致性 hash 算法( consistent hashing )

    转载:http://blog.csdn.net/sparkliang/article/details/5279393                                           ...

  5. 白话解析:一致性哈希算法 consistent hashing

    在了解一致性哈希算法之前,最好先了解一下缓存中的一个应用场景,了解了这个应用场景之后,再来理解一致性哈希算法,就容易多了,也更能体现出一致性哈希算法的优点,那么,我们先来描述一下这个经典的分布式缓存的 ...

  6. 深入一致性哈希(Consistent Hashing)算法原理

    2019独角兽企业重金招聘Python工程师标准>>> 本文为实现分布式任务调度系统中用到的一些关键技术点分享--Consistent Hashing算法原理和Java实现,以及效果 ...

  7. 一致性 hash 算法(consistent hashing)

    一致性 hash 算法(consistent hashing) consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random tre ...

  8. 一致性hash算法Consistent Hashing

    一致性hash算法Consistent Hashing 对于原有hash算法hash%n so... 1.话不多说直接上代码,原理或详解自行百度即可 import cn.pheker.utils.Ut ...

  9. kitex 中 consistent hashing 的实现

    一致性哈希算法(consistent hashing) kitex 中一致性的很多细节都和我预先理解的不一样. 这种负载均衡算法是在client侧实现的,那么client是怎么知道所有的ip的? 感觉 ...

  10. 一致性Hash(Consistent Hashing)原理剖析及Java实现

    目录 一.一致性Hash(Consistent Hashing)原理剖析 二.一致性hash算法的Java实现 一.一致性Hash(Consistent Hashing)原理剖析 引入 一致性哈希算法 ...

最新文章

  1. oracle误删scott文件如何恢复
  2. c语言多线编程程序,C语言之多线编程 来看看?
  3. jQuery 双击事件(dblclick)时,不触发单击事件(click)
  4. 【js】JavaScript parser实现浅析
  5. 钉钉新增“下班勿扰”功能:次日上班前不接受任何消息!
  6. 【mysql安装】阿里云centos7环境mysql安装
  7. 基于51单片机+LCD1602显示
  8. 学生管理系统实训报告
  9. red5流媒体服务器系统,red5 流媒体服务器配置
  10. sealos4.1部署Kubernetes单机
  11. Windows 如何完整备份驱动
  12. matlab如何整理表格数据,数据整理的程序与步骤:包括数据预处理、分类或分组、图表显示...
  13. 数据分析展示B站UP主假吃强(Cram阿强)的面目-视频与简介篇
  14. python游戏彩蛋_用python写游戏之2D跑酷游戏(一)
  15. 豆瓣电台WP7客户端 开发记录7
  16. python高级编程(6) - 对象引用,可变性和垃圾和回收
  17. MATLAB学习笔记5:绘图基础与数据可视化(中)
  18. 十个好用的iOS开发辅助工具与资源
  19. Java 输入一个年份,判断它是平年还是闰年
  20. ffmpeg音频解码重采样(立体声转成单声道)

热门文章

  1. 生成式对抗网络论文阅读整理
  2. Pandas常用函数diff和shift函数学习使用
  3. 2021-06-27Date时间
  4. JavaScrip内置对象
  5. 零知识证明 一文看懂 zkSNARK
  6. JavaSE基础——异常、File文件类
  7. JavaSE基础———Set接口中的常用类HashSet、LinkedHashSet和TreeSet
  8. 采样次数不同平均值不一样_认知的不同,才有不一样的人生
  9. 拥塞避免算法、快重传、快恢复、慢启动
  10. 使用phpstudy中的apache进行虚拟主机的配置(自定义网站名进行访问,如http://wei.com)