本文首发于:白话分布式系统中的一致性哈希算法

微信公众号:后端技术指南针

持续输出干货 欢迎关注!

通过本文将了解到以下内容:分布式系统的概念和作用

分布式系统常用负责均衡策略

普通哈希取模策略优缺点

一致性哈希算法的定义和思想

一致性哈希的基本过程

Redis集群中一致性哈希的实现

1.分布式系统的基本概念分布式系统与高并发高可用

当今高并发和海量数据处理等场景越来越多,实现服务应用的高可用、易扩展、短延时等成为必然。在此情况下分布式系统应运而生,互联网的场景无外乎存储和计算,因此分布式系统可以简单地分为:分布式存储

分布式计算

所谓分布式系统就是一批计算机组合起来共同对外提供服务,对于用户来说具体有多少规模的计算机完成了这次请求,完全是无感知的。分布式系统中的计算机越多,意味着计算和存储资源等也就越多,能够处理的并发访问量也就越大,响应速度也越快。如图为简单整体架构图:大前端 主要实现了服务应用对应的所有流量的接入,比如http://aaa.com域名下可能有N个子服务,这一层涉及很多网络流量的处理,也很有挑战,像百度的BFE(百度统一前端)接入了百度的大部分流量,每日转发1万亿次,峰值QPS1000w。

中间层 完成了各个服务的调度和分发,粒度相比大前端接入层更细致一些,这一层实现了用户的无感知体验,可以简单理解为反向代理层。

业务层 完成了数据存储、数据计算、数据缓存等,各个业务环节高度解耦,并且基于集群化来实现。集群和分布式的区别与联系

集群是从原来的单机演变来的,单台机器扛不住就加机器,直到服务负载、稳定性、延时等指标都满足,集群中的N台机器上部署一样的程序,就像一台机器被复制多份一样,这种形式就是集群化。

分布式是将一个完整的系统,按照业务功能拆分成一个个独立的子系统,这些服务之间使用更高效的通信协议比如RPC来完成调度,各个子服务就像在一台机器上一样,实现了业务解耦,同时提高了并发能力确实不赖。一个大的分布式系统可以理解拆分之后的子服务使用集群化,一个个子服务之间使用类似于RPC的协议串联,组成一个庞大的存储和计算网络。如图为简单的分布式系统结构:

注:图片来自网络 详见参考1

2.分布式系统的分发常用负载均衡策略

以分布式系统中的存储和缓存为例,如果存储集群中有5台机器,如果这时有请求,就需要考虑从哪台机器获取数据,一般有几种方法:随机访问

轮询策略

权重轮询策略

Hash取模策略

一致性哈希策略

各种方法都有各自的优缺点:随机访问可能造成服务器负载压力不均衡;轮询策略请求均匀分配,但当服务器有性能差异,无法按性能分发; 权值需要静态配置,无法自动调节;哈希取模如果机器动态变化会导致路由产生变化,数据产生大量迁移。Hash取模策略

Hash取模策略是其中常用的一种做法,它可以保证相同请求相同机器处理,这是一种并行转串行的方法,工程中非常常见。笔者在刚毕业做流量分析时就是按照报文的五元组信息做key来决定服务内的业务线程id,这样确保相同的TCP/HTTP连接被相同的线程处理,避免了线程间的通信和同步,实现了无锁化处理,所以还是很有用的。

index = hash_fun(key) % N

从上面的普通hash取模公式可以看到,如果N不变或者可以自己主动控制,就可以实现数据的负载均衡和无锁化处理,但是一旦N的变化不被控制,那么就会出现问题。Hash取模的弊端

阶段一:目前有N=4台机器S1-S4,请求拼接key通过hash函数%N,获取指定的机器序号,并将请求转发至该机器。

阶段二:

S3机器因为磁盘故障而宕机,这时代理层获得故障报警调整N=3,这时就出现了问题,如果作为缓存使用,S3机器上的所有key都将出现CacheMiss,原来存放在S1的key=abc使用新的N,被调整到S4,这样abc也出现CacheMiss,因为在S4上找不到abc的数据,这种场景就是牵一发而动全身,在缓存场景中会造成缓存击穿,如果量很大会造成缓存雪崩。

阶段三:

由于S3宕机了,因此管理员增加了一台机器S5,代理层再次调整N=4,此时又将出现类似于阶段二的数据迁移,仍然会出现CacheMiss的情况。

3.一致性哈希算法一致性哈希的定义In computer science, consistent hashing is a special kind of hashing such that when a hash table is resized, only K/n keys need to be remapped on average, where K is the number of keys, and n is the number of slots.维基百科-Consistent hashing

翻译一下:一致哈希 是一种特殊的哈希算法。

在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对K/n 个关键字重新映射,其中 K是关键字的数量,n是槽位数量。

在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。维基百科-一致性哈希

从定义可以知道,一致性哈希是一种特殊的哈希算法,区别于哈希取模,这种特殊的哈希算法实现了少量数据的迁移,避免了几乎全部数据的移动,这样就解决了普通hash取模的动态调整带来的全量数据变动。解决思路是什么

先不看算法的具体实现,先想想普通hash取模的问题根源是什么?N的变动

没错!根源就在于N的变动,那么如果N被固定住呢?并且让N很大,那么每次被移动的key数就是K_all/Slot_n,也就是有槽位的概念,或者说是小分片的概念,直白一点就是鸡蛋放到了很多很多的固定数量的篮子里:

Key_all 存储的全部key的数量

Slot_n 总的槽位或者分片数

Min_Change 为最小移动数量

Min_change = Key_all/Slot_n

Min_change 也是数据的最小分片Shard小分片的归属

这里还有一个问题要解决,将N固定且设置很大之后,数据分片shard变得非常小了,这时就有shard的所属问题,也就是比如N=100w,此时集群有10台,那么每台机器上理论上平均有10w,当然可以根据机器的性能来做差异化的归属配置,性能强的多分一些shard,性能差的少分一些shard。问题到这里,基本上已经守得云开见月明了,不过还是来看看1997年麻省理工发明的一致性哈希算法原理吧。Karger的一致性哈希算法一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得DHT可以在P2P环境中真正得到应用。一致性哈希算法数据在哈希环上的分片

正如我们前面的思考,Karger的一致性哈希算法将N设置为2^32,形成了一个0~(2^32-1)的哈希环,也就是相当于普通Hash取模时N=2^32。

注:图片来自网络 详见参考2在将数据key进行hash计算时就落在了0~(2^32-1的哈希环上,如果总的key数量为Sum,那么单个哈希环的最小单位上的key数就是:

Unit_keys = Sum/2^32

由于N非常大所以哈希环最小单位的数据量unit_keys小了很多。服务器节点和哈希环分片的分配

注:图片来自网络 详见参考2

将服务器结点也作为一种key分发到哈希环上:

con_hash(ip_key)%2^32

一致性哈希算法使用顺时针方法实现结点对哈希环shard的归属,但是由于服务器结点的数量相比2^32会少非常多,因此很稀疏,就像宇宙空间中的天体,你以为天体很多,但是相比浩渺的宇宙还是空空如也。一致性哈希的不均衡

实体服务器结点少量相比哈希环分片数据很少,这种特性决定了一致性哈希的数据倾斜,由于数量少导致服务节点分布不均,造成机器负载失衡,如图所示,服务器1的负载远大于其他机器:

注:图片来自网络 详见参考2

虚拟节点的引入:

这个说白了服务器结点不够,就让服务器的磁盘、内存、CPU全去占位置,现实生活中也这样:12306出来之前,火车站连夜排队买票,这时什么书包、水杯、眼镜都代表了张三、李四、王二麻子。

同样的道理,将服务器结点根据某种规则来虚拟出更多结点,但是这些虚拟节点就相当于服务器的分身。

比如采用如下规则在ip后缀增加#index,来实现虚拟节点的定位:

vnode_A_index = con_hash(ip_key_#A)%2^32

vnode_B_index = con_hash(ip_key_#B)%2^32

...

vnode_k_index = con_hash(ip_key_#k)%2^32

注:图片来自网络 详见参考2

这是由于引入了虚拟节点,因此虚拟节点的分片都要实际归属到真实的服务节点上,因此在实际中涉及到虚拟节点和实体结点的映射问题。新增服务器结点

注:图片来自网络 详见参考2

当管理员新增了服务器4时,原来在服务器3和服务器1之间分布的哈希环单元上的数据,将有一部分迁移到服务器4,当然由于虚拟节点的引入,这部分数据迁移不会很大,并不是服务器4和服务器1之间的数据都要顺时针迁移,因此这样就实现了增加机器时,只移动少量数据即可。删除服务器结点

注:图片来自网络 详见参考2

当服务器结点2发生宕机,此时需要被摘除进行故障转移,原来S2以及其虚拟节点上的数据都将进行顺时针迁移到下一个实体结点或者虚拟结点。

4.Redis的一致性哈希实现

Redis cluster 拥有固定的16384个slot,slot是虚拟的且被分布到各个master中,当key 映射到某个master 负责slot时,就由对应的master为key 提供服务。

每个Master节点都维护着一个位序列bitmap为16384/8字节,也就是Master使用bitmap的原理来表征slot的下标,Master 节点通过 bit 来标识哪些槽自己是否拥有,比如对于编号为1的槽,Master只要判断序列的第二位是不是为1即可。

这样就建立了分片和服务结点的所属关系,所以整个过程也是两个原则,符合上文的一致性哈希的思想。

hash_slot_index =CRC16(key) mod 16384

注:图片来自网络 详见参考4

5.总结和思考一致性哈希算法的两个关键点

一致性哈希算法是一种特殊的哈希算法,特殊之处在于将普通哈希取模的N进行固定,从而确保了相同的key必然是相同的位置,从而避免了牵一发而动全身的问题,这是理解一致性哈希的关键。

一致性哈希算法的另外一个要点就是将N固定且设置很大之后,实际上就是进行数据分片Sharding,分布的小片就要和实际的机器产生关联关系,也就是哪台机器负责哪些小分片。

但是一致性哈希算法并不是从彻底解决了由于动态调整服务器数据产生的数据迁移问题,而是将原来普通哈希取模造成的几乎全部迁移,降低为小部分数据的移动,是一种非常大的优化,在工程上基本上可以满足要求。

一致性哈希算法的关键有两点:大量固定数量的小数据块的分片

小分片的服务器归属问题一致性哈希算法的其他工程版本

像Redis并没有使用2^32这种哈希环,而是采用了16384个固定slot来实现的,然后每个服务器Master使用bitmap来确定自己的管辖slot,管理员可以根据机器的配置和负载情况进行slot的动态调整,基本上解决了最开始的几种负载均衡策略的不足。

所以假如让你设计一个一致性哈希算法,只要把握两个原则即可,并不是只有麻省理工Karger的一种哈希算法,它只是提供了一种思想和方向。天马行空

一直有个疑问问什么要用"一致性哈希算法" 这个名字,让我总和分布式系统中的一致性协议(eg最终一致性)混淆。英文原文是Consistent hashing,其中Consistent译为"一致的,连贯的",我觉得连贯的更贴切一些,以为这种特殊的哈希算法实现了普通哈希取模算法的平滑连贯版本,称为连贯性哈希算法,好像更合适,一点愚见,水平有限,看看就完事了。

5.参考资料

6.推荐阅读

7.关于本公众号

开号不久作者力争持续输出原创干货,如果文章有帮助到你,希望朋友们多多转发和分享,作者会更加有动力推出更好的文章,共同进步。

redis实现轮询算法_白话分布式系统中的一致性哈希算法相关推荐

  1. 一致性hash算法_(图文案例)一致性哈希算法详解 一点课堂(多岸教育)

    一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性 ...

  2. 一文搞懂负载均衡中的一致性哈希算法

    一致性哈希算法在很多领域有应用,例如分布式缓存领域的 MemCache,Redis,负载均衡领域的 Nginx,各类 RPC 框架.不同领域场景不同,需要顾及的因素也有所差异,本文主要讨论在负载均衡中 ...

  3. 的一致性哈希_五分钟看懂一致性哈希算法

    作者简介: 华哥 10年+后端开发工作经验, 主要分享:关于java体系的知识,如:java基础知识/数据结算/算法,Spring/MyBatis/Netty源码分析,高并发/高性能/分布式/微服务架 ...

  4. umap算法_生命科学中的 UMAP(降维算法)

    UMAP应该说是目前最好的降维算法了,能最大程度的保留原始数据的特征同时大幅度的降低特征维数. 这是<生命科学的数理统计和机器学习>的相关探讨,我试图介绍生物信息学.生物医学.遗传学等常见 ...

  5. Swift中的一致性哈希算法(补充)

    2019独角兽企业重金招聘Python工程师标准>>> 总结一下,理解算法时的几个问题,搞懂这些基本上就算理解Swift rebalnce的算法了. Swift如何保证文件的随机存储 ...

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

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

  7. 图解什么是一致性哈希算法

    1. 写在前面 周末就像太阳,总会到来,也总会离开. 此刻,没错,是周六呀!还是双休那种! 昨晚在B站看了几个长视频,导致2点才睡觉,早上一觉醒来已经10点了. 在这里温馨提示各位盆友们,虽然我们都是 ...

  8. 分布式系统中的一致性hash

    转载来源: https://zhuanlan.zhihu.com/p/92742908 通过本文将了解到以下内容: 分布式系统的概念和作用 分布式系统常用负责均衡策略 普通哈希取模策略优缺点 一致性哈 ...

  9. [图文详解]什么是一致性哈希算法,墙裂推荐收藏

    1. 写在前面 周一就像太阳,总会到来,也总会离开. 此刻,没错,是周一呀! 昨晚在B站看了几个长视频,导致2点才睡觉,早上是真的起不来. 在这里温馨提示各位盆友们,虽然我们都是年轻人,但还是要规律作 ...

最新文章

  1. pandas创建内容全是0的dataframe、pandas基于随机整数、随机浮点数创建dataframe(random numbers)
  2. 艾伟_转载:.NET内存管理、垃圾回收
  3. 死磕18个Java8日期处理,工作必用!
  4. opencv cannot open file 'opencv_calib3d249d'
  5. rancher中添加用户,赋予权限
  6. Python中断多重循环的几种思路exit_flag
  7. 非度量多维标度_16s分析作图之NMDS非度量多维尺度分析
  8. python 008 __ 小斌文档 | 元组
  9. Tornado 源码分析(一)
  10. Python--邮件处理
  11. yolov3运行及保存检测视频(包括摄像头)
  12. 【TA-霜狼_may-《百人计划》】图形2.7.2 GPU硬件架构概述
  13. 2022年公共广播火灾报警系统市场深度分析及发展研究预测报告
  14. 电商平台:京东关键词【获取商品详情、标题、图片、卖家昵称字段数据摘取】、1688拍立淘、淘宝淘口令页面展示
  15. 【字节日常实习-前端凉经】
  16. [附源码]java毕业设计基于JavaWeb生鲜O2O订购平台
  17. 北京大兴国际机北京大兴国际机场,炫酷之处,一图了解!
  18. ABAP 程序完成EXCEL文件的导入导出,OLE技术的应用
  19. 喊话程瞎子,出来道个歉真的那么难吗?
  20. linux mplayer 编译,linux平台mplayer的编译安装方法

热门文章

  1. 十年前他在马王堆送快递,如今当上航空主管,拯救客户亿元大单
  2. 苹果承认新一代iPad wifi问题 正调查原因
  3. 关于计算机科学技术的作文,关于描写计算机的作文
  4. android 地铁地图api,入门指南-地铁图 JS API | 高德地图API
  5. 请求示例curl获取电商商品详情数据API接口,批量采集
  6. 一个完整的大作业--广州市社会保障(市民)卡服务网
  7. Pandas 写入excel报错UserWarning: Ignoring URL
  8. 各种压缩算法的压缩效率,时间、压缩比等比较
  9. 关于C++的数组或者字符串的输入问题
  10. 市面上开源项目这么多,别无脑上,需谨慎行事