【朝花夕拾】基础算法之一致性Hash

算法简介

普通Hash算法

普通的Hash函数作用是散列,本质上就是将一系列在形式上具有相似性质的数据,打散成随机的、均匀分布的数据。

比如,对字符进行md5计算,得到一串的hash值。

package main

import (
    "crypto/md5"
    "fmt"
)

func main() {
    s1 := "abcd"
    date := []byte(s1)
    hs := md5.Sum(date)
    md5str := fmt.Sprintf("%x", hs)
    fmt.Println(md5str)

}

输出:e2fc714c4727ee9395f324cd2e7f331f
一致性Hash算法(Consistent Hashing)

一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式缓存中提出的,设计目标是为了解决因特网中的热点(Hot spot)问题,

核心思想:将key作hash运算, 并按一定规律取整得出0 -
$2^{32}-1$之间的值, 环的大小为 $2^{32}$,key计算出来的整数值则为key在hash环上的位置。

主要用途:解决分布式系统中对象与节点的映射关系。

go语言算法实现

导入代码实现库


go get github.com/g4zhuj/hashring

使用例子:


// virtualSpots means virtual spots created by each node

nodeWeight := make(map[string]int)
nodeWeight["node1"] = 1
nodeWeight["node2"] = 1
nodeWeight["node3"] = 2
vitualSpots := 100
hash := NewHashRing(virtualSpots)
    
//add nodes
hash.AddNodes(nodeWeight)
    
//remove node
hash.RemoveNode("node3")

//add node
hash.AddNode("node3", 3)

//get key's node
node := hash.GetNode("key")

原理及使用场景

使用场景 分布式系统中对象与节点的映射关系。

传统方案(硬哈希)是使用对象的哈希值,对节点个数取模,再映射到相应编号的节点,即 mod(key, n)。 这种方案在节点个数变动时,映射关系变为 mod(key, n+1) / mod(key, n-1),绝大多数对象的映射关系会失效而需要迁移。

详细原理

一、创建哈希环

  1. 一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为$0-2^{32}-1$(即哈希值是一个32位无符号整形),整个哈希空间环如下:
图1

上图中,可见整个空间按顺时针方向组织,0和$2^{32}-1$在零点中方向重合。

  1. 下一步,将各个服务器节点使用Hash进行一个哈希,具体可以选择服务器的ip或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,这里假设将上文中四台服务器使用ip地址哈希后在环空间的位置如下:
图2
  1. 接下来,使用如下算法定位数据访问到相应服务器:将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。

例如:我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:

图3

根据一致性哈希算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。

二、容错性

下面分析一致性哈希算法的容错性:

现假设Node C不幸宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。

一般的,在一致性哈希算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

三、扩张性

下面考虑另外一种情况,如果在系统中增加一台服务器Node X,如下图所示:

图4

此时对象Object A、B、D不受影响,只有对象C需要重定位到新的Node X 。

一般的,在一致性哈希算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它数据也不会受到影响。

综上所述,一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

四、可能问题及解决方式

一致性哈希算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。

例如系统中只有两台服务器,其环分布如下

图5

此时必然造成大量数据集中到Node A上,而只有极少量会定位到Node B上。

为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。

具体做法:在服务器ip或主机名的后面增加编号来实现。例如上面的情况,可以为每台服务器计算三个虚拟节点,于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六个虚拟节点:

图6

同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。

算法特点

  • 均衡性(Balance)

均衡性主要指,通过算法分配, 集群中各节点应该要尽可能均衡。

  • 单调性(Monotonicity)

单调性主要指,当集群发生变化时, 已经分配到老节点的key,尽可能的任然分配到之前节点,以防止大量数据迁移。

这里一般的hash取模就很难满足这点,而一致性hash算法能够将发生迁移的key数量控制在较低的水平。

  • 分散性(Spread)

分散性主要针对同一个key,当在不同客户端操作时,可能存在客户端获取到的缓存集群的数量不一致,从而导致将key映射到不同节点的问题,这会引发数据的不一致性。

好的hash算法应该要尽可能避免分散性。

  • 负载(Load)
    负载主要是针对一个缓存而言,同一缓存有可能会被用户映射到不同的key上,从而导致该缓存的状态不一致。

具体的工程应用场景

  • Apache Cassandra:在数据分区(Data partitioning)中使用到一致性哈希
  • Voldemort:LinkedIn 开发的键值(Key-Value)存储数据库,在数据分区(Data partitioning)中使用到一致性哈希
  • Akka:Akka 的 Router 使用了一致性哈希
  • Dynamo:数据划分使用了一致性哈希
  • Couchbase:在数据分区(Data partitioning)中使用到一致性哈希
  • Riak:数据划分使用了一致性哈希
  • GlusterFS:文件分布使用了一致性哈希

参考文章

https://www.cnblogs.com/mafeng/p/6808497.html

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

推荐阅读更多精彩内容