lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

上一篇说负载均衡的时候,提到redis是用一致性hash算法,但是有网友指出redis是用hash slot算法的,学业未精的我,又去学习一番。

redis cluster 有固定的 16384 个 hash slot,对每个 key 计算 CRC16 值,然后对 16384 取模,可以获取 key 对应的 hash slot。

HASH_SLOT = CRC16(key) mod 16384

为什么选择mod 16384呢?

In our tests CRC16 behaved remarkably well in distributing different kinds of keys evenly across the 16384 slots

官网说:在测试中发现,使用CRC16算法计算出来的key可以在16384个槽中均匀分布。

用一个例子看看hash slot是怎么实现的:

我们假设现在有3个节点已经组成了集群,分别是:A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用hash slot的方式来分配16384个slot 的话,它们三个节点分别承担的slot 区间是:

  • 节点A覆盖0-5460;
  • 节点B覆盖5461-10922;
  • 节点C覆盖10923-16383.

节点上使用bitmap记录各自的hash slot。

那么,现在我想设置一个key ,比如叫my_name:

set my_name *****

hash slot:CRC16('my_name')%16384 = 2412。 那么就会把这个key 的存储分配到 A 上了。

我想获取my_name

get my_name

会出现两种情况:

  1. client刚好直接访问到Node A,Node A查询自己的hash slot表,发现key->my_name在自己节点中,接着处理命令,获取my_name的值返回客户端。
  2. client访问到Node B或者Node C,发现key->my_name在Node A中,返回MOVED error。然后client重定向到该节点
GET my_name
-MOVED 2412 127.0.0.1:6381

ps: client也可以缓存各节点的hash slot map

新增一个Node D:

从各个节点的前面各拿取一部分slot到Node D上

  • 节点A覆盖1365-5460
  • 节点B覆盖6827-10922
  • 节点C覆盖12288-16383
  • 节点D覆盖0-1364,5461-6826,10923-12287

同样删除一个节点也是类似,移动完成后就可以删除这个节点了。

参考来源:

Redis Cluster Specification - Redis​redis.iohttps://www.zybuluo.com/phper/note/195558​www.zybuluo.com高级开发不得不懂的Redis Cluster数据分片机制​juejin.im

 

编辑于 2019-08-18
posted on 2020-12-05 14:29  白露~  阅读(308)  评论(0编辑  收藏  举报