面试官:知道为什么RedisCluster有16384个槽么?

引言

我在《那些年用过的Redis集群架构(含面试解析)》一文里提到过,现在redis集群架构,redis cluster用的会比较多。

面试官:知道为什么RedisCluster有16384个槽么?_第1张图片

HASH_SLOT=CRC16(key) mod 16384,计算出映射到哪个分片上,然后Redis会去相应的节点进行操作!

那大家思考过,为什么有16384个槽么?ps:CRC16算法产生的hash值有16bit,该算法可以产生2^16-=65536个值。换句话说,值是分布在0~65535之间。那作者在做mod运算的时候,为什么不mod65536,而选择mod16384?

其实我当初第一次思考这个问题的时候,我心里是这么想的,作者应该是觉得16384就够了,然后我就开始查这方面资料。

很幸运的是,这个问题,作者是给出了回答的!https://github.com/antirez/redis/issues/2576

作者原版回答如下:

  • Normal heartbeat packets carry the full configuration of a node, that can be replaced in an idempotent way with the old in order to update an old config. This means they contain the slots configuration for a node, in raw form, that uses 2k of space with16k slots, but would use a prohibitive 8k of space using 65k slots.

  • At the same time it is unlikely that Redis Cluster would scale to more than 1000 mater nodes because of other design tradeoffs.

So 16k was in the right range to ensure enough slots per master with a max of 1000 maters, but a small enough number to propagate the slot configuration as a raw bitmap easily. Note that in small clusters the bitmap would be hard to compress because when N is small the bitmap would have slots/N bits set that is a large percentage of bits set.

因此,能看懂上面那段话的读者。这篇文章不用看了,因为作者讲的很清楚了。本文只是对上面那段话做一些解释而已。

正文

基础

我们回忆一下Redis Cluster的工作原理!

127.0.0.1:7000>cluster meet 127.0.0.1:7001

如下图所示

面试官:知道为什么RedisCluster有16384个槽么?_第2张图片

定期发送ping/pong消息,交换 数据信息,如下图所示。

面试官:知道为什么RedisCluster有16384个槽么?_第3张图片

在这里,我们需要关注三个重点。

  • (1)交换什么数据信息

  • (2)数据信息究竟多大

  • (3)定期的频率什么样

到底在交换什么数据信息?

面试官:知道为什么RedisCluster有16384个槽么?_第4张图片

注意看红框的内容,type表示消息类型。 另外,消息头里面有个myslots的char数组,长度为16383/8,这其实是一个bitmap,每一个位代表一个槽,如果该位为1,表示这个槽是属于这个节点的。

到底数据信息究竟多大?myslots[CLUSTER_SLOTS/8]。这块的大小是:16384÷8÷1024=2kb这里的重点是:节点数量越多,消息体内容越大。

消息体大小是10个节点的状态信息约1kb。

那定期的频率是什么样的?

  • (1)每秒会随机选取5个节点,找出最久没有通信的节点发送ping消息

  • (2)每100毫秒(1秒10次)都会扫描本地节点列表,如果发现节点最近一次接受pong消息的时间大于cluster-node-timeout/2 则立刻发送ping消息

因此,每秒单节点发出ping消息数量为1+10*num(node.pong_received>cluster_node_timeout/2)

那大致带宽损耗如下所示,图片来自《Redis开发与运维》

640?wx_fmt=png

讲完基础知识以后,我们可以来看作者的回答了。

回答

(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。myslots[CLUSTER_SLOTS/8]65536÷8÷1024=8kb(2)redis的集群主节点数量基本不可能超过1000个。(3)槽位越小,节点少的情况下,压缩率高

ps:文件压缩率指的是,文件压缩前后的大小比。

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

总结

希望大家有所收获!

你可能感兴趣的:(面试官:知道为什么RedisCluster有16384个槽么?)