一致性哈希算法详解

一、什么是哈希

散列表,是根据键直接访问在指定储存位置数据的数据结构。通过计算一个关于键的函数也称为哈希函数,将所需查询的数据映射到表中一个位置来访问记录,加快查找速度。这个映射函数称做「散列函数」,存放记录的数组称做散列表。

散列函数能使对一个数据序列的访问过程更加迅速有效,是一种空间换时间的算法,通过散列函数数据元素将被更快定位。

二、常见的hash算法

MD5算法

MD5消息摘要算法(MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),MD5算法将数据(如一段文字)运算变为另一固定长度值,是散列算法的基础原理。由美国密码学家 Ronald Linn Rivest设计,于1992年公开并在 RFC 1321 中被加以规范。

CRC算法

循环冗余校验(Cyclic Redundancy Check)是一种根据网络数据包或电脑文件等数据,产生简短固定位数校验码的一种散列函数,由 W. Wesley Peterson 于1961年发表。生成的数字在传输或者存储之前计算出来并且附加到数据后面,然后接收方进行检验确定数据是否发生变化。由于本函数易于用二进制的电脑硬件使用、容易进行数学分析并且尤其善于检测传输通道干扰引起的错误,因此获得广泛应用。

MurmurHash

MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。由 Austin Appleby 在2008年发明,并出现了多个变种,与其它流行的哈希函数相比,对于规律性较强的键,MurmurHash的随机分布特征表现更良好。

这个算法已经被很多开源项目使用,比如libstdc++ (4.6版)

三、常用的散列方法:

1.直接定址法:取关键字或关键字的某个线性函数值为散列地址,这个线性函数的定义多种多样,没有标准。

2.数字分析法:假设关键字是以r为基的数,并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。

3.平方取中法:取关键字平方后的中间几位为哈希地址。通常在选定哈希函数时不一定能知道关键字的全部情况,取其中的哪几位也不一定合适,而一个数平方后的中间几位数和数的每一位都相关,由此使随机分布的关键字得到的哈希地址也是随机的,取的位数由表长决定。

4.折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。

5.取模法:取关键字被某个不大于散列表表长 m 的数 p 除后所得的余数为散列地址。即 hash(key) = key % p(p<= M),不仅可以对关键字直接取模,也可在折叠法、平方取中法等运算之后取模。对 p 的选择很重要,一般取素数或 m,若 p 选择不好,容易产生冲突。

四、普通hash算法存在的问题

如果我们需要对mysql数据库进行分库分表,如分成三张表,那么我们如果使用普通hash的话,假设我们选择取模法,需要选一个字段对3取余,成功分区如下


1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0

这时候呢如果我们需要分成4张表这时候就需要对4取余


1 % 4 = 1
2 % 4 = 2
3 % 4 = 3
4 % 4 = 0
5 % 4 = 1
6 % 4 = 2

如果我们想查3应该去3这个分区,按照之前的hash却是去0,数据乱了,新加入的数据还好可以按照新的映射关系,但是老的数据是没办法修改的,需要对全部的数据重新计算hash才能不影响到查询,这个工作量基本是不可实现的,所以这时候就需要使用一致性hash算法

五、一致性hash算法--hash环

一致性哈希算法(Consistent Hashing)最早在论文《Consistent Hashing and Random Trees: Distributed Caching Protocols for Relieving Hot Spots on the World Wide Web》中被提出。简单来说,一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希空间环如下:

还是以上面mysql分库分表的例子:

下一步将各个表使用Hash进行一个哈希,具体可以选择表中的唯一整数型字段进行哈希,这样每台机器就能确定其在哈希环上的位置,哈希后在环空间的位置如下: 

 这样就相当于hash值在0-1073741824的在第一张表,1073741824-2147483648的在第二张表,2147483648-3221225472在第三张表,3221225472-4294967296在第四张表

如果说后续需要添加节点,如加个表五,那么只需要随便选个节点,比如将第一个表中数据复制一半到新的表中就可以其他映射关系都不会收到影响

一致性hash存在的最大问题是会产生数据偏移,所以一般都是倍数扩容

六、 一致性hash算法应用--redis虚拟槽技术

虚拟槽技术应用于redis集群分区,具体可以看https://blog.csdn.net/zhang09090606/category_10909179.html?spm=1001.2014.3001.5482

1.虚拟槽技术
虚拟槽分区巧妙地使用了哈希空间,槽并不是真实存在只是逻辑上的,使用分散度良好的哈希函数把所有 数据映射到一个固定范围的整数集合中,整数定义为槽(slot )。这个范围 一般远远大于节点数,比如Redis Cluster 槽范围是 0~16383 。槽是集群内数据 管理和迁移的基本单位。采用大范围槽的主要目的是为了方便数据拆分和集群扩展。每个节点会负责一定数量的槽如下图,每个节点管理了3276个槽

2.数据分配:

当插入数据时分以下步骤

(1)首先通过CRC16算法算出redis key的散列值

(2)将此散列值对槽数也就是16383取余算出该数据应该进入到哪个槽中

(3)redis会根据管理的映射关系查到该槽归哪个节点管理

(4)将该数据放入该节点中

3.节点的伸缩:

当新增一个节点时,例如插入node-6时发生了以下操作
(1)将node-1管理的槽分配一半给node-6,此时node-1管理的槽为0-1638,node-6管理的槽为1639-3276

(2)将node-1中分配出去的槽对应的数据复制到node-6中

4.虚拟槽技术的优点

(1)伸缩时无需复制大量数据,只需复制一个节点的一半数据即可

(2)可以单个新增,即便不倍数扩容也可以保证映射关系,但是实际还是建议倍数扩容,不然会发生数据偏移(有的节点数据多有的节点数据少 )
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值