分布式系统基石之一(一致性 hash 算法)

发表于 3年以前  | 总阅读数:334 次
  • 一致性 hash —— 基础类型
  • 一致性 hash —— 虚拟节点
  • Golang 实现
  • 结构定义
  • hash 环的初始化
  • hash 环添加节点
  • 一致性 hash 请求

一致性哈希

简单哈希 hash(object)%N 是最常用的算法,这种均衡性可能还行,但是稳定性比较差,不适用于分布式系统,因为分布式系统节点的增删是常见的需求,用这种简单的哈希算法来分布,在 N 变化的时候,会导致乾坤大挪移般的分布变化。

哈希算法本质是对一个固定输入产生固定输出的算法,最本质的可以先从两个方面衡量哈希算法的适用性:

  • 平衡性:指哈希的结果能够尽可能分布到所有的节点的值域中,这样所有节点的值域都能得到利用(旁白:说白了,就是均衡喽,9个 key ,3个节点,最理想的就是每个节点处理3个)
  • 单调性:指如果已经有一些内容通过哈希计算,分布到对应的节点中,当有新的节点加入系统时候,那么哈希的结果应能够保证原有已经分布的内容可以被映射到新的节点中去(或者在原地),而不会被映射到旧的节点;
  • 这个是一个非常重要的考量,单机的简单哈希算法之所以不适用于分布式系统,就是因为这个单调性无法满足;

重点:单调性阐述的内容怎么理解呢?

增删节点都会导致新值域的产生,单调性说的就是:新值域要能从原有分布 key 里面分摊压力,原有值域却要尽量不落到原有已经分布的 key。

举个例子,假设有 key 集合:[ k1, k2, k3, k4, k5, k6, k7, k8, k9 ] ,有三个节点 [ A, B, C ] 。哈希分布之后 A [k1, k5, k8] ,B [ k2, k6, k9 ] , C [ k3, k4, k7 ]。

场景 :现在增加一个节点 D

  • 单调性好的例子:增加节点后,导致分布变成:A [ k5, k8] ,B [ k2, k6, k9 ] , C [ k3, k4 ] ,D [ k1, k7 ]。

  • 我们看到 D 作为新加进来的节点,只是从 A,C 里面匀了一些 key 过来,原来 A,B,C 的内容全都不变,这就是一个单调性比较好的例子

  • 单调性差的例子:如果说,因为加了一个 D 节点,变成:A [k2, k9,k8] ,B [ k4, k6 ] , C [ k3, k5 ] ,D [ k1, k7 ]。这种结果看起来平衡性也不错,但是映射关系就有太多的变化,单调性太差了。这么大的映射变化,对应大分布式系统中,可能就是不能接受的数据迁移量;

一致性 hash —— 基础类型

最基础的一致性 hash 算法就是把节点直接分布到环上,从而划分出值域, key 经过 hash( x ) 之后,落到不同的值域,则由对应的节点处理。类似下图,物理节点直接映射到环上:

最常见的值域空间大小是:2^32 - 1,节点落到这个空间,来划分不同节点所属的值域,现在我们举例就不搞这么大了,搞个简单的空间。

举一个例子,假设环的值域是 100(旁白:这个你自己随便定,反正就是一个边界值而已),A 的值域是 [ 0, 20 ) ,B 的值域是 [ 20, 70 ) ,C的值域是 [ 70, 100 )。(旁白:值域怎么来,A,B,C节点经过 hash 计算出一个 [0,100] 的值,落在环上,就会划分出两个区域)

上述基本的一致性哈希算法有明显的缺点:

1 . 随机分布节点的方式使得很难均匀的分布哈希值域(旁边:你看我黑圈圈在圆上的位置是不均衡的);

2 . 在动态增加节点后,原先的分布就算均匀也很难再继续保证均匀;

3 . 增删节点带来的一个较为严重的缺点是:

a . 当一个节点异常时,该节点的压力全部转移到相邻的一个节点;

b . 当一个新节点加入时只能为一个相邻节点分摊压力;

一致性 hash —— 虚拟节点

针对基础一致性 hash 的缺点一种改进算法是引入虚节点(virtual node)的概念。这个本质的改动:值域不再由物理节点划分,而是由固定的虚拟节点划分,这样值域的不均衡就不存在了。

步骤:

  • 系统初始时就创建许多虚节点,虚节点的个数一般远大于未来集群中机器的个数,将虚节点均匀分布到一致性哈希值域环上,功能与基本一致性哈希算法中的节点相同;
  • 为每个物理节点分配若干虚节点;
  • 操作数据时,首先通过数据的哈希值在环上找到对应的虚节点,进而查找元数据找到对应的真实节点(旁白:所以这部分元数据是需要存下来的);

使用虚节点改进有多个优点:

  • 首先,一旦某个节点不可用,该节点将使得多个虚节点不可用,从而使得多个相邻的真实节点承载失效节点的压力;
  • 同理,一旦加入一个新节点,可以分配多个虚节点,从而使得新节点可以负载多个原有节点的压力,从全局看,较容易实现扩容时的负载均衡;

那么我们最直观的想到这种样子:

但其实这个还差点意思,就是虚拟节点和物理节点的绑定关系不能这样绑定,最好打散绑定。不然还是做不到上面说的两个优点,1)增节点的时候要能为多个节点分摊压力,2)删节点的时候要能让多个节点承担压力。

怎么打散?举一个简单交叉打散的例子:[A, B, C, B, C, A, C, A, B] (旁白:我这由于虚拟节点太少了,只能意思意思了,懂意思就行)

我标红的表示假设 B 节点故障,假设流量顺时针后移的话,那么就能用到 A,C 两个节点来分摊流量了,你看这样是不是就比之前要高级点。

由于有虚拟节点,所以可以保持值域不变,当出现增删节点只需要调整物理节点映射虚拟节点的关系即可,从而达到流量打散的目的。

Golang 实现

说了那么多,现在分析一个 golang 的一致性哈希的实现,非常有参考意义:

结构定义

首先,你需要一个抽象环(或者说序列的结构)。


type Hash func(data []byte) uint32
type Map struct {
    hash     Hash   // 计算 hash 的函数 
    replicas int    // 这个是副本数,这里影响到虚拟节点的个数
    keys     []int  // 有序的列表,从大到小排序的,这个很重要
    hashMap  map[int]string // 可以理解成用来记录虚拟节点和物理节点元数据关系的
}

举个例子,如果你有3个节点,replicas 设置成 3 ,那么就在环上有 9 个节点,9 个元素(后续就以此举例子)。

hash 环的初始化

然后你需要一个 New 的函数,把内存结构创建出来,初始化下,这个返回的你可以认为是一个空环:


func New(replicas int, fn Hash) *Map {
    m := &Map{
        replicas: replicas,
        hash:     fn,
        hashMap:  make(map[int]string),
    }
    if m.hash == nil {
        // 默认可以用 crc32 来计算hash值
        m.hash = crc32.ChecksumIEEE 
    }
    return m
}

hash 环添加节点

func (m *Map) Add(keys ...string) {
    // keys => [ A, B, C ]
    for _, key := range keys {
        for i := 0; i < m.replicas; i++ {
            // hash 值 = hash (i+key)
            hash := int(m.hash([]byte(strconv.Itoa(i) + key)))
            m.keys = append(m.keys, hash)
            // 虚拟节点 <-> 实际节点
            m.hashMap[hash] = key
        }
    }
    sort.Ints(m.keys)
}

比如,A,B,C 三个节点,replicas 为3,那么就:

  • 节点输入:keys => [ A, B, C ]

  • 用来计算 hash 值的输入是:i + key,也就是输入为:[ 0A, 1A, 2A, 0B, 1B, 2B, 0C, 1C, 2C]

  • 计算出来的 hash 序列是:m.keys = [ hash(0A), hash(1A), hash(2A), hash(0B), hash(1B), hash(2B), hash(0C), hash(1C), hash(2C) ]

  • 我们认为 hash 函数是有比较好的平衡性的,那么计算出的值,应该就是随机均衡打散的,我们认为是符合概率分布的;

  • 最后会把这个 hash 值的序列做一个排序,做完排序之后,其实就完成了值域的打散划分;

一致性 hash 请求

func (m *Map) Get(key string) string {
    if m.IsEmpty() {
        return ""
    }
    // 根据用户输入key值,计算出一个hash值
    hash := int(m.hash([]byte(key)))
    // 查看值落到哪个值域范围?选择到虚节点
    idx := sort.Search(len(m.keys), func(i int) bool { return m.keys[i] >= hash })
    if idx == len(m.keys) {
        idx = 0
    }
    // 选择到对应物理节点
    return m.hashMap[m.keys[idx]]
}

以上就是一个完整的一致性hash的实现了,是不是特别简单,这个实现就能适用于我们常用的分布式缓存的。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/q69cRbRFSDOC0haY-z_uhA

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录