编辑
2023-10-27
缓存中间件
0
请注意,本文编写于 204 天前,最后修改于 50 天前,其中某些信息可能已经过时。

目录

什么Redis集群?
关于Redis集群的槽
Redis集群如何进行槽指派?
Redis集群的重分片
Redis集群的故障转移是如何做的?

什么Redis集群?

一个Redis集群通常由多个节点(node)组成,在刚开始的时候,每个节点都是相互独立的,它们都处于一个只包含自己的集群当中,要组建一个真正可工作的集群,必须将各个独立的节点连接起来,构成一个包含多个节点的集群。连接各个节点的工作可以使用CLUSTER MEET命令来完成(CLUSTER MEET <ip> <port>),向一个节点node发送CLUSTER MEET命令,可以让node节点与ip和port所指定的节点进行握手(handshake),当握手成功时,node节点就会将ip和port所指定的节点添加到node节点当前所在的集群中。

关于Redis集群的槽

Redis集群没有使用一致性hash算法的,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置到哪个槽,每个集群的每个节点负责一部分hash槽。CRC16算法产生的hash值有16bit,也就是2^16=65535个值,为什么选择mod 16384而不是mod 65535?

为什么redis集群的最大槽数是16384个?

1、消息大小考虑:尽管crc16能得到65535个值,但redis选择16384个slot,是因为在Redis集群中,发送心跳消息的消息头,16384的消息只占用了2k,而65535则需要8k,消息头过于庞大,浪费带宽。

2、集群规模设计考虑:集群设计最多支持1000个分片,16384是相对比较好的选择,需要保证在最大集群规模下,slot均匀分布场景下,每个分片平均分到的slot不至于太小。

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

Redis集群如何进行槽指派?

​ Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽(slot),数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0个或最多16384个槽。当数据库中的16384个槽都有节点在处理时,集群处于上线状态(ok);相反地,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态(fail)。所以在构建一个集群之后,需要通过向节点发送CLUSTER ADDSLOTS命令,将一个或多个槽指派(assign)给节点负责,当数据库中的16384个槽都已经被指派给了相应的节点,集群会进入上线状态。比如:

shell
CLUSTER ADDSLOTS 0 1 2 ... 5000 # 将槽0-槽5000指派给当前节点负责。

​ Redis会用一个二进制数组,以0为起始索引,16383为终止索引,对slots数组中的16384个二进制位进行编号,并根据索引i上的二进制位的值来判断节点是否负责处理槽i:

​ 如果slots数组在索引i上的二进制位的值为1,那么表示节点负责处理槽i。

​ 如果slots数组在索引i上的二进制位的值为0,那么表示节点不负责处理槽i。

Redis集群的重分片

Redis集群的重新分片操作可以将任意数量已经指派给某个节点(源节点)的槽改为指派给另一个节点(目标节点),并且相关槽所属的键值对也会从源节点被移动到目标节点。重新分片操作可以在线(online)进行,在重新分片的过程中,集群不需要下线,并且源节点和目标节点都可以继续处理命令请求。

Redis集群的故障转移是如何做的?

​ Redis集群中的节点分为主节点(master)和从节点(slave),其中主节点用于处理槽,而从节点只需要用于复制某个主节点,并在被复制的主节点下线时,代替下线主节点继续处理命令请求,槽位则转换到从节点上,并把从节点升级为主节点。如果故障转移完成后,原主节点恢复了,那么它会成为原从节点的从节点。

具体故障转移的流程

​ 当一个从节点发现自己正在复制的主节点进入了已下线状态时,从节点将开始对下线主节点进行故障转移,以下是故障转移的执行步骤:

​ 1)复制下线主节点的所有从节点里面,会有一个从节点被选中。

​ 2)被选中的从节点会执行SLAVEOF no one命令,成为新的主节点。

​ 3)新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己。

​ 4)新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽。

​ 5)新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。

本文作者:whitebear

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!