负载均衡--hash slot算法  

负载均衡--hash slot算法
 

上一篇说负载均衡的时候,提到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.
负载均衡--hash slot算法
 

节点上使用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
负载均衡--hash slot算法
 

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

参考来源:

​juejin.im
编辑于 2019-08-18