「这是我参与 2022 首次更文挑战的第 8 天,活动详情查看:2022 首次更文挑战」
君子以遏扬善,顺天休命。
前面已经介绍过了 redis 的数据结构和编码方式,今天分享一下 redis 的主从同步的核心原理,其实就是在主从、主备、哨兵集群中,从服务器如何从主服务器同步缓存信息。
Redis 主从同步主要配置项
首先,先简介一下 Redis 主从复制相关的配置项:
# 主节点的 ip 和端口,需要注意的是 slaveof 是异步命令
slaveof <masterip> <masterport>
# mater 节点的密码,如果主节点设置有密码,从节点复制数据需要配置密码
masterauth <master-password>
# 设置从节点只能读数据
slave-read-only yes
# 主从节点tcp 延迟是否允许,默认不允许,如果是yes将会将数据包进行合并发送,带来主从延迟
repl-disable-tcp-nodelay no
# 主从之间心跳检测频率,默认为10s钟,主节点检测从节点的状态
repl-ping-slave-period 10
# 主从同步数据时,从节点个数小于3个或者主从同步延迟小于10s,主节点会拒绝写命令。
min-slaves-to-write 3
min-slaves-max-lag 10
Redis 同步数据分类
Redis 主从同步是通过 slave of 命令来控制从节点从那个主服务器获取同步信息,当主节点的数据发生变化时,会通过 Redis 通信协议将数据发送到从节点,主节点一般只有一个,负责数据的写入,从节点一般是多个而且都是只读的。总的来说,redis 主从同步是使用 psync 命令来实现的,数据同步分为全量同步和增量同步。
全量同步: 用于在初次同步数据或者无法进行同步数据情况下,主节点把所有数据都发送到从节点,是一项很重的操作。主节点收到全量同步的命令后,执行 bgsave,在后台生成一个 rdb 文件,并使用一个缓冲区来记录从 bgsave 开始后的所有写命令。主节点执行完 bgsave 后,将 rdb 文件发送到从节点,从节点首先清除自己的旧数据,然后载入新的 rdb 文件恢复数据。主节点也会从复制缓冲区将所有的写命令发送给从节点,从节点执行增量命令,数据状态则会更新至主节点状态。如果从节点开启了 bgrewriteaof 的执行,从而保证 aof 更新至主节点最新状态。
增量同步: 用于网络中断情况后的同步,只将中断期间的主节点写命令发送到从节点即可。增量同步有三个概念:同步偏移量、积压缓冲区、服务器运行 ID。
同步偏移量(offset):主节点和从节点分别维护一个偏移量,分别代表各自的数据最新值。这里可以简单理解为每一个数据操作的版本号。积压缓冲区:redis的积压缓冲区是由 主节点维护的,长度固定、先进先出的队列,默认大小为1MB。积压缓冲区主要是备份数据给从节点同步数据使用,不论有多少个从节点,积压缓冲区只有一个。服务运行 ID(runid): 无论是从节点和主节点在启动后,都会随机生成一个 ID,由 40 个随机的 16 进制字符组成,runid用来识别一个redis节点,通过info server命令可以查看runid。
在主从数据同步阶段, 还维持着心跳机制:PING 和 REPLCONF ACK。
PING 是主节点向从节点发送命令进行检测从节点状态,默认是 10s 一次,由 repl-ping-slave-period 来控制。REPLCONF ACK 则是从节点向主节点发送同步命令,发送方式为 REPLCONF ACK {offset} 从节点每秒钟一次。
Redis 同步数据的主要步骤
上一节讲述了主从同步的两种方式以及同步相关操作,在实际同步过程中的同步过程如下图所示:
-
1 如果从节点之前未执行过
slaveof命令,则从节点发送 psync ? -1到主节点请求全量复制 -
2 如果从节点之前执行过
slaveof命令,则发送psync <runid> <offset>命令,其中 runid 是上次复制主节点的 runid ,offset 则是上次复制截止时从节点保存的复制偏移量。 -
3 主节点接收到
psync命令,以及当前服务器状态,决定执行全量复制还是增量复制。如果主节点的 runid 与从节点 runid 相同,且从节点发送的 offset 之后的数据在复制挤压缓冲区都存在,则回复从节点 continue ,表示进行增量复制,从节点等待主节点发送其增量数据即可。 如果主节点的 runid 与从节点 runid 不同,或者从节点发送的 offset 在缓冲区已经不存在了(在队列中被挤出),则回复 `fullresync ``, 表示需要进行全量复制,其中 runid 和 offset 表示主节点的 runid 和 数据的偏移量 offset。