天天看点

Redis Cluster集群为何是16384个哈希槽

转载请声明出处哦~,本篇文章发布于 fushengwushi 的博客:https://www.fushengwushi.com/archives/1616

我们都知道,对于客户端请求的key,redis是根据公式 

HASH_SLOT=CRC16(key) mod 16384

,计算出映射到哪个分片上,然后Redis会去相应的节点进行操作。

Redis Cluster集群为何是16384个哈希槽

CRC16

算法产生的hash值有16bit,该算法可以产生65536(2^16)个值。换句话说,值是分布在0~65535之间。那作者在做

mod

运算的时候,为什么不

mod

 65536,而选择

mod

 16384?这个问题,作者是给出了回答的,详见: https://github.com/antirez/redis/issues/2576,下面我们来具体的讲一下。

1. 如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。

redis集群的节点之间会定期发送ping/pong消息,交换数据信息的,交换的数据信息,由消息体和消息头组成。

消息体无外乎是一些节点标识,IP,端口号,发送时间等等,这里我们主要关注的是消息头:

Redis Cluster集群为何是16384个哈希槽

src/cluster.h (redis-6.0.9)

可以看到有个字段名为 myslots 的char数组,长度为 CLUSTER_SLOTS/8,CLUSTER_SLOTS为常量16384,所以该数组长度为16384/8,这其实是一个bitmap,每一个位代表一个槽,如果该位为1,表示这个槽是属于这个节点的。

该数组所占空间大小为 16384÷8÷1024=2kb,当槽位为65536时,这块的大小是: 

65536÷8÷1024=8kb

。消息体中会携带一定数量的其他节点的信息,节点信息里同样包含其槽位信息,节点数大约占集群节点总数量的十分之一,至少是3个节点的信息。节点数量越多,消息体内容越大。

因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。

2. redis的集群主节点数量基本不可能超过1000个

如上所述,集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者,不建议redis cluster节点数量超过1000个。

3. 槽位越小,节点少的情况下,压缩率高

Redis主节点的配置信息中,它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中,会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。 如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。

综上所述,作者决定取16384个槽,不多不少,刚刚好!

相关链接

https://www.cnblogs.com/rjzheng/p/11430592.html

https://zhuanlan.zhihu.com/p/99037321

继续阅读