Redis数据分布一致性哈希

一致性哈希

一致性哈希的原理:

把所有的哈希值空间组织成一个虚拟的圆环(哈希环),整个空间按顺时针方向组织。因为是环形空间,0 和2^32-1 是重叠的。

假设我们有四台机器要哈希环来实现映射(分布数据),我们先根据机器的名称或者IP 计算哈希值,然后分布到哈希环中(红色圆圈)。

现在有4 条数据或者4 个访问请求,对key 计算后,得到哈希环中的位置(绿色圆圈)。沿哈希环顺时针找到的第一个Node,就是数据存储的节点。

在这种情况下,新增了一个Node5 节点,不影响数据的分布。

删除了一个节点Node4,只影响相邻的一个节点。

谷歌的MurmurHash 就是一致性哈希算法。在分布式系统中,负载均衡、分库分表等场景中都有应用。

一致性哈希解决了动态增减节点时,所有数据都需要重新分布的问题,它只会影响到下一个相邻的节点,对其他节点没有影响。

但是这样的一致性哈希算法有一个缺点,因为节点不一定是均匀地分布的,特别是在节点数比较少的情况下,所以数据不能得到均匀分布。解决这个问题的办法是引入虚拟节点(Virtual Node)。

比如:2 个节点,5 条数据,只有1 条分布到Node2,4 条分布到Node1,不均匀。

Node1 设置了两个虚拟节点,Node2 也设置了两个虚拟节点(虚线圆圈)。

这时候有3 条数据分布到Node1,1 条数据分布到Node2。

Redis 虚拟槽分区

Redis 既没有用哈希取模,也没有用一致性哈希,而是用虚拟槽来实现的。

Redis 创建了16384 个槽(slot),每个节点负责一定区间的slot。比如Node1 负责0-5460,Node2 负责5461-10922,Node3 负责10923-16383。

Redis 的每个master 节点维护一个16384 位(2048bytes=2KB)的位序列,比如:序列的第0 位是1,就代表第一个slot 是它负责;序列的第1 位是0,代表第二个slot不归它负责。

对象分布到Redis 节点上时,对key 用CRC16 算法计算再%16384,得到一个slot的值,数据落到负责这个slot 的Redis 节点上。

查看key 属于哪个slot:

redis> cluster keyslot leon

注意:key 与slot 的关系是永远不会变的,会变的只有slot 和Redis 节点的关系。

问题:怎么让相关的数据落到同一个节点上?

比如有些multi key 操作是不能跨节点的,如果要让某些数据分布到一个节点上,例如用户2673 的基本信息和金融信息,怎么办?

在key 里面加入{hash tag}即可。Redis 在计算槽编号的时候只会获取{}之间的字符串进行槽编号计算,这样由于上面两个不同的键,{}里面的字符串是相同的,因此他们可以被计算出相同的槽。

user{2673}base=…

user{2673}fin=…

127.0.0.1:7293> set a{qs}a 1
OK
127.0.0.1:7293> set a{qs}b 1
OK
127.0.0.1:7293> set a{qs}c 1
OK
127.0.0.1:7293> set a{qs}d 1
OK
127.0.0.1:7293> set a{qs}e 1
OK

问题:客户端连接到哪一台服务器?访问的数据不在当前节点上,怎么办?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值