为什么Redis集群分片最大槽数是16384个
为什么Redis集群分片最大槽数是16384个?
GitHub上已有关于这个问题的解答,why redis-cluster use 16384 slots? · Issue #2576 · redis/redis (github.com),这里只做大概解释
Redis集群通过CRC16算法对key进行哈希并对16384取模来决定该key具体放在哪个槽位,而该算法的hash结果有16位,也就是65536个值,那为啥不分配65536个槽而是16384(2^14)个?
首先翻译一下作者的解答:
正常的心跳数据包带有节点的完整配置,可以用幂等方式用旧的节点替换旧节点,以便更新旧的配置。这意味着它们包含原始节点的插槽配置,该节点使用2k的空间和16k的插槽,但是会使用8k的空间(使用65K的插槽)。同时,由于其他设计折衷,Redis集群不太可能扩展到1000个以上的主节点。因此16k处于正确的范围内,以确保每个主机具有足够的插槽,最多可容纳1000个矩阵,但数量足够少,可以轻松地将插槽配置作为原始位图传播。请注意,在小型群集中,位图将难以压缩,因为当N较小时,位图将设置的slot / N位占设置位的很大百分比。
翻译了又好像没翻译,还是没看懂,,,
其实总结起来就是以下三个因素的考虑。
(1)如果槽位个数为65536,发送的心跳信息头达到8k,发送的心跳包过大。
上图即为Redis节点发送的信息头结构,其中占据最大空间的就是myslots[CLUSTER_SLOTS/8]。如果槽位为65536个,大小为65536 / 8 / 1024 = 8 kb。如果槽位为16384个,大小为16384 / 8 / 1024 = 2 kb。在Redis集群中,Redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536个,发送的消息头太大,浪费带宽。
(2)Redis的集群主节点数量基本不可能超过1000个,16384个槽位已经够用
集群节点越多,心跳包的消息体内携带的数据越多。如果节点超过1000个,也会导致网络拥堵。因此Redis作者不建议Redis cluster节点数量超过1000个。 那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。
(3)节点一定的情况下,槽位越少,压缩比越高,容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots /N很高的话(N表示节点数),bitmap的压缩率就很低。也就是说当节点数一定时,哈希槽数量很多的话,bitmap的压缩率就很低,不易传输。