一致性哈希算法
来源:互联网 发布:ubuntu numix主题包 编辑:程序博客网 时间:2024/06/09 22:19
前面专门介绍过几种常见的数据分片(Sharding),主要包括范围分片(Range)和哈希(Hash)分片两种大的策略,其中哈希分片最简单的Round Robin方法(直接按照机器数取模)存在一个明显的缺点,当机器数增加或者减少的时候,所有的数据都要进行重新的哈希分配。这个问题的本质原因是因为机器和数据哈希分布之间强耦合,因此针对这个缺陷主要有两个解决方案一种是引入虚拟桶的概念,分两步映射(key-partition和partition-machine),另一种方案就是一致性哈希,引入哈希空间(将key-partition和partition-machine映射到同一个哈希空间),解除了机器和数据分布的耦合关系。这两天看了《大数据日知录》第一章的数据分片与路由,这里主要讲一下一致性哈希的实现原理。
整体架构
一致性哈希是分布式哈希表的一种实现,主要有Chord(和弦)系统提出,其变种也广泛应用于诸如Dynamo和Cassandra等分布式存储系统。与虚拟桶的初衷相同,都是为了解决机器和数据分布的耦合关系,但是一致性哈希则对key-partition和partition-machine使用同一个哈希函数,这样就可以将机器和数据分片都在同一个空间,每一个机器负责规定范围的数据分片。
一致性哈希算法将哈希空间抽象成一个环状结构,比如一个长度为5的二进制空间(可以表示0-31的空间),在空间结构上首尾相连,组成一个环状序列。对于数据根据Key值哈希到这个空间,对于机器同样根据根据一定的key(比如ip+port)映射到同一个空间,这样机器就相当于将整个空间截成了几段,每个机器节点负责一段,同时每个节点记录其前驱节点和后继节点。下图就是一个长度为5的哈希空间,有五个节点,五个节点的哈希值分别是5,14,20,25,29,每个节点负责(
查找key
上一节可以看到一致性哈希算法没有统一的控制节点,也就是说对于客户端来说并不知道需要请求那个节点去获得某个key的值,也不能通过一个主控节点去获得某个key的存储节点。这也正是一致性哈希广泛用于分布式系统的重要原因,不需要主控节点,也就不存在单点问题,同时又有良好的可扩展性。
虽然没有主控节点,但是客户端知道所有节点,可以向任何一台节点发送请求,前面我们说过每个节点都知道其前驱节点和后继节点,所以任何一个收到请求的节点会首先通过哈希函数获得请求key的哈希值,假设为j,判断是否在其负责的范围如果没有则将其转发给后继节点查找,如此循环直到找到一个节点,其负责范围包括j(即上图中节点下角大于等于j的最小编号节点)。
如果按照这样的方法查找显然效率很低,一个请求如果查找这么久才返回,延迟也太高了。所以为了加快速度,一致性哈希算法在每个节点配置了一个路由表,存储了m条(前面提到的二进制哈希空间长度,比如前面的5)路由信息。分别是比当前节点多
有了路由表,如果客户端要请求的key不在改节点,怎么可以直接根据该表尽可能快的找到目标节点。
一致性哈希路由算法
假设要查找key的哈希值为hash(key)=j,初始请求的节点为
1. 首先
2. 如果key不在
3. 如果key不在后继节点,这时就需要查找路由表(这里的路由表示距离为1开始所以存储了后继节点的信息,和第二步有点重复,个人感觉也许可以不用存储后继节点的路由信息进行优化),找到小于j的最大编号节点(如果所有路由表都大于j,则选择最后一项路由信息作为下一个查询节点)作为查询节点,
还是以上面的例子为例,假设初始查询的节点是
节点变更
一致性哈希算法一般应用于分布式的环境,避免不了新增加节点,以及节点宕机的故障。一致性哈希算法也同样设计了一套算法用于增加,减少节点。
增加节点
如果现有的哈希空间中新增加一个节点,假设为
为了保证多个节点加入的时候不出现问题,一致性哈希提供了一套稳定性检测的算法去保证新节点的加入和离开。每个节点都会周期性的执行稳定性检测算法,保证目前节点的连接关系的正确性。
稳定性检测算法
在新加入节点的时候,首先安装前面说的找到新节点的后继节点,也就是当前新节点哈希值所在的节点
稳定性检测算法的具体流程如下:
1. 假设
2. 如果
3. 假设
4.
还是以前面的例子为例,加入一个新的节点
之后节点
之后当节点
当然这个时候还不算完成,加入节点后,部分节点的路由表已经不再适用,除了稳定性检测,每个节点也会周期性进行路由表的更新检测,用来更新节点的路由表。
节点的离开
节点的离开分为两种,正常离开和异常离开,对于正常离开的节点,可以自动更新前驱和后继节点,并转移数据。对于异常离开的节点,通常都是由于机器的故障,这时就会导致数据的丢失,因此通常会在节点的后继节点中保留多份副本保证数据的安全。
虚拟节点
为了解决刚开始提到哈希的随机导致的节点负载不均衡,可以使用虚拟节点的方法解决,具体稍微复杂一点可以参考 Cassandra的一致性哈希(Consistent Hashing)和虚拟节点(Virtual Nodes)的关系
参考资料
- 《大数据日知录》第一章数据分片与路由
- 分布式缓存负载均衡的规则处理:虚拟节点对一致性哈希的改进
- Cassandra的一致性哈希(Consistent Hashing)和虚拟节点(Virtual Nodes)的关系
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 一致性哈希算法
- 1045: 邮票组合问题*
- iOS安装CocoaPods详细过程
- AES/CryptoJS/PHP 加密解密
- 2.4.uboot配置和编译过程详解
- Java unix时间戳 移除秒毫秒部分
- 一致性哈希算法
- 二分贪心 T题
- setenforce: SELinux is disabled解决办法
- mybatis常见错误(文件配置)
- 表单控件大小
- Linux 文本处理工具
- ubuntu indigo skeleton tracker(骨骼跟踪)
- python使用opencv2人脸识别
- 表单控件状态(禁用状态)