consistent hash(一致性哈希算法)
一、产生背景
今天咱不去长篇大论特别详细地讲解consistent hash,我争取用最轻松的方式告诉你consistent hash算法是什么,如果需要深入,Google一下~。
举个栗子吧:
比如有 N 个 cache 服务器,需要将一个object 映射到 N 个 cache 上,我们可以用类似下面的方法计算 object 的 hash 值,然后均匀的映射到到 N 个 cache 上:
hash(object)%N
比如object是“hello”,hash(object)是100,N为3,100%3=1,这个数据会被存到第1个cache上(0、1、2三个cache)。这样就能解决一堆数据放到N个cache上的问题。
现在有个突发情况,0、1、2三个cache中1损坏了!
怎么办呢,cache 1上的数据首先需要迁移,可用cache数量变为2,这个时候我们需要重新计算所有数据的hash值,上面的公式变成了这样:
hash(object)%(N-1)
这次重新计算意味着每一份数据hash之后的结果几乎都变了!也就是意味着在cache系统中会发生大规模cache失效,数据访问会直接冲击cache后面的服务器,好玩了,崩了。
咋个办呢,consistent hash出现了!
二、算法原理
consistent hash简单的说,就是要在cache数量变化时,能够尽可能小的改变已存在 key 映射关系,也就是增加一个cache或者减少一个cache服务器,对已经存在的缓存数据不要产生大影响。怎么做到呢,,,
我们先想象一条链子,第一个格子是0,最后一个格子是2^32-1,这条链子就是一个地址空间为2^32的hash值空间,现在将链子首位相连,组成一个ring,就像下面这样(这里画图太麻烦了,下面的环环相关的图来自互联网,侵删吧):
然后考虑我们由object1~object4这样四个数据,通过hash算法后映射到这个ring上【类似这样:hash(object1)=key1】
这里应该很好理解,4个数据得到4个key,接下来我们要将cache服务器也映射到这个ring上,假设由3个cache服务器,分别是cache A、cache B、cache C,然后用hash算法:hash(cache A)=key A,将3个cache服务器丢到这个ring上,就可用得到如下结果(计算cache服务器的hash值时可以用其ip等信息):
然后顺着这个ring,收集object数据,遇到cache的时候就丢进去,这样就可以将数据和cache对应起来,于是我们可以得到如下结果:
object1:Cache A
object4:Cache B
object2/object3: Cache C
ok,这样就完成了数据映射,然后我们考虑一下前面普通hash算法遇到的cache服务器数量变化的情况,看一下ring hash是否解决了这个问题。
假设cache B掉线
这个时候可以发现只有原先映射到Cache B上的object4收到了影响,需要转移到Cache C上。
如果增加一个Cache结点呢?假设增加一个Cache D:
这个时候只需要将object2转移到Cache D上,其他的没有变化。是不是很神奇?
这里可能大家会意识到一个问题,当cache服务器数量少的时候,这个算法很容易导致数据分布不均匀,所以ring hash中还有一个虚拟节点的概念,前面只剩下cache A和cache C的例子中A上有1个数据,而C中存了3个,我们将cache(假设用ip值表示)加上一个编号,然后进行hash运算,得到更多的虚拟cache结点:
hash("192.168.0.1#1")
hash("192.168.0.1#2")
hash("192.168.0.2#1")
hash("192.168.0.2#2")
类似上面这样,一个cache服务器就对应了2个hash值,这样我们再丢到ring上就会得到如下结果:
这时候object1就会落在Cache A2上,object2会落在Cache A1上,物理上其实A1和A2都是cache A,通过这种方式直观看我们将原先的1、3分布变成了2、2分布(A上1个数据C上3个数据变成A上2个数据B上2个数据)
引入“虚拟节点”后,映射关系就从 { 对象 -> 节点 } 转换到了 { 对象 -> 虚拟节点 },于是乎这个算法的平衡性就更好了。
ok,一致性hash算法的原理就介绍到这里,下面可以看groupcahce中的consistent hash如何实现了。
三、groupcache中的consistent hash
终于要看代码了!!!
源码主要就如下几个package,今天我们看一下第一个package:【package consistenthash】的内容
从上图我们可以看到,这里只需要关注consistenthash.go这源码文件,里面有2个类型:Hash和Map,1个函数New,Map类型有4个不可导出的属性以继3个绑定的方法。
下面一个个看吧~
1、类型Hash(需要记得Hash是一个函数类型哦)。
2、Map类型(Map类型的第一个属性就是上面的Hash类型变量hash,replicas属性表示的是副本数,还记得上面我们提到的为了解决平衡性问题而引入的虚拟节点的概念吗?这些虚拟节点这是这里描述的副本数)。
3、New()函数(这个函数明显就是用来获取上面的Map类型变量实例的,初始化副本数、hash函数、hashMap表,hashMap表的key是一个表示cache服务器或者副本的hash值,value为一个具体的cache服务器,这样就完成了Cache A、Cache A1、Cache A2等副本全部映射到Cache A的功能。
4、IsEmpty()函数(这个函数就没啥可讲的了,非空判断)
5、Add()函数(将缓存服务器加到Map中,比如Cache A、Cache B作为keys,如果副本数指定的是2,那么Map中存的数据是Cache A#1、Cache A#2、Cache B#1、Cache B#2的hash结果)
6、Get()函数(这个函数相对复杂一点,比如有一个数据:name="张三"这条数据需要存,这时候通过这个函数选择一个cache服务器,返回的string类型可以是服务器ip,比如:"192.168.0.1",从而调用者能够将name="张三"存到"192.168.0.1"上)
ok,讲完了,今天的内容有点多,可能需要多花点时间消化一下~
下一讲我们介绍groupcachepb这个package,当然不可避免地要介绍一下Protocol Buffers了,行,今天就讲到这里!
consistent hash(一致性哈希算法)的更多相关文章
- hash环/consistent hashing一致性哈希算法
一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的 ...
- 一致性哈希算法(consistent hashing)(转)
原文链接:每天进步一点点——五分钟理解一致性哈希算法(consistent hashing) 一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网 ...
- 一致性哈希算法学习及JAVA代码实现分析
1,对于待存储的海量数据,如何将它们分配到各个机器中去?---数据分片与路由 当数据量很大时,通过改善单机硬件资源的纵向扩充方式来存储数据变得越来越不适用,而通过增加机器数目来获得水平横向扩展的方式则 ...
- _00013 一致性哈希算法 Consistent Hashing 新的讨论,并出现相应的解决
笔者博文:妳那伊抹微笑 博客地址:http://blog.csdn.net/u012185296 个性签名:世界上最遥远的距离不是天涯,也不是海角,而是我站在妳的面前.妳却感觉不到我的存在 技术方向: ...
- 一致性哈希算法(Consistent Hashing Algorithm)
一致性哈希算法(Consistent Hashing Algorithm) 浅谈一致性Hash原理及应用 在讲一致性Hash之前我们先来讨论一个问题. 问题:现在有亿级用户,每日产生千万级订单,如 ...
- 一致性哈希算法(Consistent Hashing) .
应用场景 这里我先描述一个极其简单的业务场景:用4台Cache服务器缓存所有Object. 那么我将如何把一个Object映射至对应的Cache服务器呢?最简单的方法设置缓存规则:object.has ...
- 转 白话解析:一致性哈希算法 consistent hashing
摘要: 本文首先以一个经典的分布式缓存的应用场景为铺垫,在了解了这个应用场景之后,生动而又不失风趣地介绍了一致性哈希算法,同时也明确给出了一致性哈希算法的优点.存在的问题及其解决办法. 声明与致谢: ...
- 分布式_理论_08_Consistent Hash(一致性哈希算法)
一.前言 五.参考资料 1.分布式理论(八)—— Consistent Hash(一致性哈希算法)
- 一致性哈希算法(consistent hashing)PHP实现
一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简单哈希 ...
随机推荐
- Linux虚拟机搭建本地yum源
Yum本地源的配置 本教程是在虚拟机里安装Red Hat Enterprise Linux 7 ,以其为例使用iso文件进行Yum本地源的配置.所使用的软件如下: (1)虚拟机:Vmware work ...
- OneNote中添加代码问题
OneNote是我最常用的笔记本,然而粘贴代码很麻烦,之前只能屏幕截图如Snipaste自带截图什么的,后来才知道win10自带有win+shift+s自动剪切到草图板上的功能, 然而还是很麻烦. 在 ...
- jQuery实现节点克隆
为了便于在DOM节点进行添加或者删除节点元素,使用克隆的方法比较方便,下面是js部分的主要代码 var container = $('.recordCon'); var cloneDom = cont ...
- H5 _浏览器通知功能使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- swust oj 1011
二叉排序树的实现和查找 1000(ms) 10000(kb) 2782 / 6301 按照给定的关键字集合,建立二叉排序树.在建立的二叉排序树上查找指定的关键字,查找成功,输出找到该关键字比较的次数: ...
- VIM批量缩进
方法一 1.按 ctrl + shif + ; 进入底行模式 2.将所要批量缩进的行号写上,按照格式:“行号1,行号2>”输入命令,如要将4至11行批量缩进一个tab值,则命令为“4,11&g ...
- Android简单计时器
本文利用ContextMenu(上下文菜单),Chronometer实现简单计数器. Main.xml: <?xml version="1.0" encoding=" ...
- PTA第四次作业
题目 7-1 计算职工工资 1.设计思路 (1)第一步:观察题意了解各个参数与所需函数在题目中的意义: 第二步:设计算法编写函数,让函数的功能实现题目中所需的功能: 第三步:运行程序检测是否错误. ( ...
- 中文转拼音without CJK
Xamarin写Android程序时,通常要使用按中文首字母分组显示(如通讯录) . 于是需要被迫包含CJK,不过包含后包肯定是会变大的,于是....自己写了一个硬枚举的中文转拼音的类. 原理是这样的 ...
- 详解AMD规范及具体实现requireJS在工程中的使用
前面的话 由CommonJS组织提出了许多新的JavaScript架构方案和标准,希望能为前端开发提供统一的指引.AMD规范就是其中比较著名一个,全称是Asynchronous Module Defi ...