redis请求路由

redis3.0后官方集群方案 节点路由通过哈希槽实现

在介绍哈希槽之前,先带着几个问题进入,正所谓,深入一点,会更美好

  1. 有几种常用的路由算法
  2. 哈希槽具体怎么实现
  3. 为什么redis要选择哈希槽

首先,我们来看 有几种常用的路由算法

按范围路由

例如:有1——100的key,A,B,C,D四个节点。按key值将1——25分布到A节点,26——50分布到B节点,51——75分布到C节点,76——100分布到D节点。
这个算法策略有几个限制:

  1. 因为是顺序范围的,所以key必须是数字。
  2. 节点分配不够灵活。新增删除是需要大量转移。
  3. 可能会造成热点节点的问题,因为是按真实的key值,可能会存在某段key值相对集中,而其他段key值很松散。举个例子有1,6,11,16,17,18,19,20。这个8个key值,从1——20,按范围分布到4个节点,则1落到A节点。6落到B节点。11落到C节点。而16,17,18,19,20全部集中落到D节点。这样就造成了热点节点的问题。
hash后按节点取模

这种路由算法策略,通过将key值做hash后变为数值,然后将这个数值与节点数取模,从而判断具体key应该存放到哪个节点上。
相对于 按范围路由 有几个优点:

  1. key值不需要是数值,因为可通过hash算法计算。
  2. 因为是hash算法重新计算,所以在节点上相对比较均匀。

举个例子,还是1——20个key,且hash后假设值为连续的1——20.则取模节点数量4后,对应的分布如下图所示:
redis请求路由算法策略

增加节点,如此时增加新节点E。此时当前数据查询时将按5取模查找节点,短时间内会有大量缓存穿透。例如如下图所示为能命中的key.蓝色数字框所示
redis请求路由算法策略

减少节点,如减少D节点,此时查询能命中的key如下图蓝色区域所示
redis请求路由算法策略

这个算法策略存在几个问题:

  1. 节点变更时:命中率极低
  2. 节点变更时:存在大量垃圾数据在原先的节点上无法被访问到
一致性hash

一致性hash算法是如何解决上面普通hash取模节点变更造成的缓存雪崩问题的呢?
一致性hash算法,采用环形hash空间结构,大致可以想象一个圆环空间,这个圆环分为2的32次幂个小段。从0到2^32 - 1。如下图所示:其中箭头所指为各个段的段号,省略中间段号,只显示起始和终点段号 0和2^32 -1。
redis请求路由算法策略

假设现在有4个redis节点,ABCD,将各个节点的ip通过hash算法(crc16)后,散列到这个哈希环中。如下图所示。
redis请求路由算法策略
那么数据如何存放呢,数据key过来后,按同样的hash算法路由到对应的环段中,落到环段顺时针的第一个节点上。如下图所示,key1落到C节点,key2落到B节点,key3和key4落到D节点,key5和key6落到A节点。
redis请求路由算法策略
此时如增加一个新节点E,则key3节点将落到新增的E节点上,如下图。
也就是说在E节点添加上来时,key3命中E节点,会被击穿。可以看到这里可能会影响的也只是BD节点间的这段数据
redis请求路由算法策略
此时如减少一个节点D,则key3和key4将挂载路由到A节点,如下图。
也就是说在D节点删除时,key3和key4会被击穿。可以看到这里可能会影响的也只是BD节点间的这段数据
redis请求路由算法策略
如上图所示:因为A节点承载了之前D节点的数据,导致数据大量倾斜到A节点,容易引发A节点机器宕机并最终发生雪崩的问题。
这里引入虚节点的概念,而真实节点不再hash到环上。想象下均匀分布在环上的一个个节点,它们都是虚节点,数据可以均匀分布挂载到虚节点上,而最终将虚节点挂靠到实节点上。如下图:A1——C3都是虚节点。
如吃此时有ABC3个实节点:

  • A节点管理挂载A1,A2,A3虚节点及其数据;
  • B节点管理挂载B1,B2,B3虚节点及其数据;
  • C节点管理挂载C1,C2,C3虚节点及其数据;

此时:新增D节点,则可动态将 A1和B1虚节点挂载到D节点上。
同理,若删除C节点,可动态将 C1挂到A节点上,C2和C3挂到B节点上。感觉这里有点像哈希槽的影子了。

redis请求路由算法策略

Hash槽

redis3.0后的官方集群方案 Redis Cluster 实现了hash槽。
在3.0以前 Redis Sharding 集群方案被普遍应用,且实现一致性hash算法。

hash槽采用slot(槽)的概念,一共分为16384个槽。使用期间数据key hash后对16384取模后,决定放入哪个槽中,而16384个槽也会被分配到对应的节点上被管理。
例如:有三个节点ABC,对应将16384个槽分配下去
A: 0 ~ 5461
B: 5461 ~ 10922
C: 10922 ~ 16384

此时如新增节点D,则其他节点从前部分配部分槽位给D,对应槽位中的数据key也会分配过去,分配完成后如下:
A:1365 ~ 5461
B:6826 ~ 10922
C:12287 ~ 16384
D:0 ~ 1365;5461 ~ 6826;10922 ~ 12887;

同理减少一个节点,则此节点遗留下来的槽位也将分配给其他节点。
hash槽的特性:

  1. 解耦数据与节点之间的关系,数据只和槽位有关;
  2. 节点自身维护槽映射关系,简化节点扩容和收缩的难度;
为什么是16384个槽

redis节点间发生心跳消息,消息头中的大小与槽位正相关,槽位太多,消息头太大,心跳包过大,而reids集群节点的个数基本不超过1000个,对应16394个槽刚好够用。

相关文章:

  • 2022-12-23
  • 2021-10-20
  • 2021-10-23
  • 2021-11-16
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-05-21
  • 2021-06-05
  • 2021-08-19
  • 2021-11-25
  • 2021-05-14
相关资源
相似解决方案