浅谈-一致性哈希算法

更多文章,请关注我的个人博客:www.ahey.net

引言

哈希算法,多应用于多数框架的底层实现,在JAVA中与其相关的有HashMap、HashTable等。

首先抛几个问题

  • 都知道Hashmap底层使用了hash(取模)算法,它与一致性hash算法有什么区别呢?
  • 在分布式缓存中,hash算法起了很大的作用,它也是上述提到的取模算法吗?
  • 取模法与一致性哈希算法有什么区别?

什么是哈希算法

hash即散列,哈希算法又称散列算法,将任意长度的二进制值映射为较短的固定长度的二进制值(哈希值),哈希值是一段数据唯一且极其紧凑的数值表示形式,常用于快速查找和加密算法。

传统取模法(以Hashmap为例)

HashMap底层结构是数组+链表+红黑树。数组相当于一个bucket,在bucket这一层就用到了取模法。

假设数组的长度为n,当一个Node(key-value)加入时,先计算key的hash值,再通过 (n -1)& hash 的位操作,得到bucket的下标。这里的位操作其实就是取模算法 hash % n的优化版。这时候问题来了,由于数组容量必定有限,当需要扩容(新增Node节点)时,Hashmap会rehash(重建hash表),可想而知重建会导致大量的key需要迁移并重新计算下标。 故Hashmap源码中提到了要合理设置初始长度和负载因子,以“内存换性能”的操作来避免rehash。

取模思路如下
假设数组初始长度n = 5,增加结点至n = 6,最终导致全部数据都需进行迁移,改变下标。

20200731152435758_1941699246.jpg

换个角度思考,是否可以做到,在扩容的时候尽最大化地减少迁移的操作,并且保证原来的key仍在原来的位置(在分布式缓存系统中,这点尤为重要,否则容易引起缓存雪崩等情况)

一致性哈希算法

引自wiki
一致哈希 是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对K/n 个关键字重新映射,其中K是关键字的数量,n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。

其实一致性哈希算法也是一种取模法,只不过不直接对服务器数量进行取模分发,而是对2^32进行取模,以此解决重新散列的问题。

实现原理大致如下

  • 构造由2^32个点位组成的环形hash空间

  • 将服务器节点映射到hash空间

  • 将存储对象映射到hash空间

  • 将对象沿顺时针转动,碰到的第一个服务器节点,即当前对象应缓存的节点

将上述原理概括成描述一致性哈希算法的规则:环形空间,节点映射,对象映射,顺时针相遇

它目前已经应用于AWS Dynamodb高可用 Nosql数据库Memcached分布式缓存、Nginx负载均衡等

一致性哈希基于分布式缓存的应用

为什么说一致性哈希是一种特殊的哈希算法,可以借助分布式缓存的例子来说明。

假设现在有三个服务器节点A、B、C,三条待缓存的键值对数据a、b、c。

初始节点

  • 将三个服务器节点通过hash(ip地址) % 2^32 取模得到一个整数值(介于0 ~ 2^32),定位到环形空间上
20200731163639418_10607236.jpg
  • 将三个缓存对象通过hash(key) % 2^32 取模得到一个整数值(介于0 ~ 2^32),定位到环形空间上
20200731171432756_1761578491.png
  • 将缓存对象沿顺时针“转动”,当第一个遇到的服务器节点,就是缓存对象对应存储的节点

如下图所示,缓存对象a在服务节点A上存储,缓存对象b在服务节点B上存储...

20200731180418926_624189149.png

节点故障

  • 假设此时节点B出现故障下线了,按照一致性哈希的规则中的“顺时针相遇”,缓存对象b应该与服务节点C相遇,存储位置变动,而其他节点按兵不动,不受影响
20200731180042941_566711142.png

新增节点

  • 假设此时新增一个节点D,位于A与C之间,如下图,按照一致性哈希的规则中的“顺时针相遇”可知,所有缓存对象无需再次转动
20200731180751711_289411648.png
  • 假设此时新增一个节点E,位于A与B之间,如下图,按照一致性哈希的规则中的“顺时针相遇”可知,缓存对象b与服务节点E相遇,存储位置变动
20200731181540803_91107481.png

hash环倾斜

在描述基于分布式缓存的应用时,看似一切都很理想化。
但是会遇到一种情况,实际服务节点的映射位置可能比较极端,进而造成数据倾斜,这种情况会导致大多数的缓存对象都集中在一个节点,失去了哈希算法存在的意义。

20200731182843005_87592856.png

虚拟节点

hash算法无法保证绝对的平衡,一致性哈希算法容易导致数据倾斜,故它又引入了“虚拟节点”,即实际节点在hash空间的复制节点,两者关系为1:n,虚拟节点在hash空间中以hash值排列

总结

一致性哈希算法,相较于常规的取模法,解决了增删节点导致的重新散列的问题,基于“环形空间,节点映射,对象映射,顺时针相遇”的规则,加上虚拟节点的引入,很大程度地解决了分布式系统的心结,故它常用于Nginx负载均衡、Dynamodb分布式数据库等。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342