redis_集群

8 min read

集群

1 主从模式

redis可以以主从模式进行运行,其中主节点支持读写,从节点只支持读。主从模式最大的难点就在于如何同步。即从节点如何同步主节点的数据。

目前的redis都是使用了SYNC/PSYNC命令进行同步,主要有全量同步,部分同步。

全量同步主要是在初次复制的时候,他的流程是主节点bgsave创建rdb文件,并发送给从节点,从节点接收rdb文件恢复数据。后续会采用增量同步的方式,来讲期间执行的写指令同步给从节点,有的地方也把这部分增量同步归为部分同步。

部分同步用于从节点断线一段时间后重连,从缓冲区获取断开期间所有的写指令,从服务器接收并执行这些指令来完成同步。

FROM chatgpt 可能有错误
全量复制(Full Resynchronization)
全量复制是在从节点刚连接到主节点时进行的一次完整复制,目的是让从节点完全拷贝一份主节点的数据。全量复制的过程如下:

从节点向主节点发送PSYNC命令,要求进行全量复制。
主节点接收到命令后,会开始进行RDB持久化操作,将数据集保存到磁盘上的RDB文件中,并将这个RDB文件发送给从节点。
从节点接收到RDB文件后,会将其加载到内存中,并更新自己的数据库状态,从而完成全量复制。
全量复制的缺点是在大数据集的情况下,需要传输大量的数据,可能会对网络带宽和传输时间造成较大的压力。

部分复制(Partial Resynchronization)
部分复制是一种增量复制方式,只传输主节点和从节点之间的增量数据,从而减少了网络传输的数据量。部分复制分为正常的增量复制和断点续传两种情况。

正常的增量复制:从节点连接到主节点后,会向主节点发送PSYNC命令,主节点会记录下从节点的复制偏移量,并将后续的增量数据传输给从节点。如果主节点没有记录到从节点的复制状态,或者从节点请求的数据已经过期,主节点会触发全量复制。

断点续传:当从节点和主节点之间的网络连接中断时,从节点会记录自己最后一次接收到的复制偏移量,并等待网络连接恢复。网络连接恢复后,从节点会向主节点发送PSYNC <runid> <offset>命令,并将自己的复制偏移量和之前记录的复制偏移量发送给主节点。主节点会判断是否可以进行增量复制,如果可以,则从上次断开连接的位置开始传输增量数据,从节点再次接收增量数据并更新自己的数据集。

需要注意的是,部分复制的实现需要在主节点和从节点上维护复制状态,并且增量数据的传输和应用需要考虑到命令的顺序和丢失的情况,因此需要使用复制积压缓冲区等机制来确保数据的完整性和一致性。

1.1 部分同步的细节

主从节点都维护一个偏移量offset,主服务器每次向从服务器传N个字节的数据(指令),那么主服务器偏移量+N,从服务器收到后也+N。如果当前有1主3从,主offset=100,从=100,此时需要同步10字节的数据,就发送10字节出来,主offset=110,从有三台假如两台都收到了并更新为110,但是另一台因为掉线了没收到,重新上线后offset还是100.

这样这台100的从机器和110的主机器就出现了没同步的状态,好在主节点维护了一个1M大小的复制积压缓冲区(replication backlog),这个缓冲区记录了主节点发送给从节点的指令列表,当然大小有限,超过了就会淘汰老的数据。经过对比发现从节点落后10个字节,只需要从队列头部往后数10个字节拿出来即可。当然如果掉线太久,差的超过了缓冲区大小,就只能全量同步了。

另外一个同步过程中的重要数据是runId,也就是机器的标识,需要传递主节点的runId,来找对应的数据,当主节点切换后,发现runId不一致,则直接进行全量同步。

2 Sentinel哨兵

一个或多个哨兵节点来监视主从服务器节点,哨兵们以10s的频率与主服务器发送INFO指令获取当前的状态,主服务器也会将从节点的信息同步给哨兵,然后就可以连上从服务器。哨兵节点之间也会互相连接,串通一气。

当主节点下线后,哨兵们会选出一个leader,对下线的主服务器进行failover故障转移。将选出一个从节点提升为主节点,并修改其他从节点指向的主节点信息为刚晋升的这个主节点,同时将已经下线的这个节点,也设置为新主的从节点,防止他封建复辟。

3 集群

哨兵可以在小规模下使用,但是当足够大的数据场景下,就必须使用集群这种分shard的思路。通过CLUSTER MEET ip:port指令可以快速和其他节点联通为一个集群。

在集群中采用了哈希槽slot的方式进行数据分配,一共有16383个slot,分给多个主节点,这里使用了一致性哈希,每个节点存储的hash值是一个范围。这样当添加或删除节点的时候,可以保证只需要少量的节点进行数据迁移。