算法 — 系统设计中一致性哈希算法的实现

5 篇文章 0 订阅
4 篇文章 0 订阅

1、设计设计需求

水平切分Horizontal Sharding:
Sharding的基本思想就要把一个数据库切分成多个部分放到不同的数据库(server)上,从而缓解单一数据库的性能问题。不太严格的讲,对于海量数据的数据库,如果是因为表多而数据多,这时候适合使用垂直切分,即把关系紧密(比如同一模块)的表切分出来放在一个server上。如果表并不多,但每张表的数据非常多,这时候适合水平切分,即把表的数据按某种规则(比如按ID散列)切分到多个数据库(server)上。

这时水平切分就会产生一个问题,假如我们来拆分 某个带id的xxxtables数据表
我们有10台数据库的机器,于是想到按照 id % 10 进行拆分,这样做的问题是啥?

假如10台机器不够用了,我现在新买了1台机器,原来的%10,就变成了%11,几乎所有的数据都要进行位置大迁移。
在这里插入图片描述

过多的数据迁移会造成的问题有:

  1. 慢,牵一发动全身
  2. 迁移期间,服务器压力增大,容易挂
  3. 容易造成数据的不一致性

2、节点个数取模

一个简单的一致性Hash算法场景:

  • 将 key 模一个很大的数,比如 360
  • 将 360 分配给 n 台机器,每个机器负责一段区间
  • 区间分配信息记录为一张表存在 Web Server 上
  • 新加一台机器的时候,在表中选择一个位置插入,匀走相邻两台机器的一部分数据

比如 n 从 2 变化到 3,只有 1/3 的数据移动
在这里插入图片描述
3台机器变4台机器时,数据与节点分布情况:
在这里插入图片描述

以上场景说明,这个版本的缺陷:

  • 增加一台服务器之后,该新服务器上的数据全从周围的1~2台服务上来
  • 这1-2台服务器的短时间内读压力增大很多,影响到正常服务
  • 每次只能从1~2台机器匀数据
  • 数据分配无法做到绝对均匀

3、一致性 Hash 算法 Consistent Hashing

传统方案是使用对象的哈希值,对节点个数取模,再映射到相应编号的节点,这种方案在节点个数变动时,绝大多数对象的映射关系会失效而需要迁移;而一致性哈希算法中,当节点个数变动时,映射关系失效的对象非常少,迁移成本也非常小。

下面看下具体方案:

将整个 Hash 区间看做环,这个环的大小从 0 ~ 359 变为 0~ 2^64 - 1,将机器和数据都看做环上的点,引入 Micro shards / Virtual nodes 的概念:一台实体机器对应 1000 个 Micro shards / Virtual nodes,每个 virtual node 对应 Hash 环上的一个点,每新加入一台机器,就在环上随机撒 1000 个点作为 virtual nodes,需要计算某个 key 所在服务器时 ,计算该key的hash值——得到0~2 ^ 64-1的一个数,对应环上一个点- - 顺时针找到第一个virtual node,该virtual node 所在机器就是该key所在的数据库服务器 。

新加入一台机器做数据迁移时 ,1000 个 virtual nodes 各自向顺时针的一个 virtual node 要数据。
在这里插入图片描述
设计哈希函数 Hash(key),要求取值范围为 [0, 2^32)
各哈希值在上图 Hash 环上的分布:时钟12点位置为0,按顺时针方向递增,临近12点的左侧位置为2^32-1。
在这里插入图片描述
下一步将各个服务器使用Hash进行一个哈希,具体可以选择服务器的ip或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,这里假设将上文中四台服务器使用ip地址哈希后在环空间的位置如下:
在这里插入图片描述
接下来使用如下算法定位数据访问到相应服务器:将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。

例如我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:
  在这里插入图片描述
根据一致性哈希算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。

下面分析一致性哈希算法的容错性和可扩展性。现假设Node C不幸宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性哈希算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

下面考虑另外一种情况,如果在系统中增加一台服务器Node X,如下图所示:
在这里插入图片描述
此时对象Object A、B、D不受影响,只有对象C需要重定位到新的Node X 。一般的,在一致性哈希算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它数据也不会受到影响。

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

另外,一致性哈希算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。例如系统中只有两台服务器,其环分布如下:

在这里插入图片描述
此时必然造成大量数据集中到Node A上,而只有极少量会定位到Node B上。为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。具体做法可以在服务器ip或主机名的后面增加编号来实现。例如上面的情况,可以为每台服务器计算三个虚拟节点,于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六个虚拟节点:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RachelHwang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值