专栏Redis 修行录个人主页手握风云目录一、主从复制概述1.1. 核心作用1.2. 主从节点规则二、复制配置三、三大复制拓扑结构3.1. 一主一从3.2. 一主多从3.3. 树形主从四、复制底层原理4.1. 建立复制4.2. 全量复制4.3. 部分复制4.4. 实时复制 心跳检测一、主从复制概述1.1. 核心作用在分布式系统当中为了解决服务单点故障的风险通常会把同一份数据生成多个副本部署到多台不同的服务器上以此实现故障恢复与负载均衡的能力。Redis 的主从复制就是基于这一思想设计的数据副本机制可以为同一份数据维护多个 Redis 副本实例。主从复制是 Redis 实现高可用的底层基础哨兵、Redis 集群这些高可用方案全部都是构建在主从复制能力之上。主从复制最核心要解决两类现实问题一是单 Redis 节点的单点故障问题单个节点宕机就会造成服务不可用二是单节点的性能瓶颈问题单台机器的 CPU、内存、网络资源有限读写并发能力存在上限。1.2. 主从节点规则参与复制的 Redis 实例划分为主节点 master 与从节点 slave 两种角色。角色之间存在明确约束每一个从节点只能够绑定唯一的一个主节点但是一个主节点可以同时挂载若干个从节点。数据复制的数据流具备单向性数据只能由主节点流向从节点从节点的数据变更无法反向同步回主节点。借助主从复制架构可以实现读写分离的业务模式。业务写请求全部交给主节点处理读请求可以分发到各个从节点执行以此分担主节点的访问压力。但原生的主从复制存在明显短板当主节点发生故障宕机的时候从节点不会自动升级成为新的主节点故障恢复需要人工介入操作这也是后续哨兵机制需要解决的核心痛点。二、复制配置Redis 搭建主从复制所有配置修改的均只针对从节点主节点不需要做任何配置改动。首先复制一份 Redis 原生配置文件作为从节点专属配置文件修改配置文件将 daemonize 设置为 yes开启后台守护进程模式端口号自定义。随后以独立端口启动从节点实例通过启动参数指定主节点的地址与端口。cp /etc/redis.conf ./slave1.conf cp /etc/redis.conf ./slave2.conf# 启动多个实例 redis-server ./slave1.conf redis-server ./slave2.conf此时的 3 个 Redis 实例还只是各自为政没有构成主从关系。修改从节点配置文件写入 slaveof 主节点IP 主节点端口Redis 重启之后复制关系自动生效。实例启动成功后使用 redis‑cli 分别连接主节点与从节点。在主节点执行写入命令就能够观察到数据会自动同步到从节点以此验证主从复制链路工作正常。redis-cli -p 6379 redis-cli -p 6380如果想要查看主从复制的详细运行状态可以执行 info replication 指令这条命令会输出大量复制相关统计字段。除了建立复制关系slaveof 命令还可以完成断开复制与切换主节点的操作。在从节点执行 slaveof no one就会断开和原有主节点之间的复制关系同时该从节点晋升成为独立的主节点。执行该操作之后从节点本地已经拥有的数据不会被清除只是不再接收原主节点后续同步过来的新数据。生产环境下还需要关注安全性、只读、网络延迟三类配置。当主节点配置requirepass访问密码时从节点必须配置 masterauth 参数参数值和主节点密码保持一致否则从节点无法完成鉴权复制流程会直接中断。从节点默认开启 slave‑read‑onlyyes 只读配置。由于复制数据流只能单向由主流向从从节点发生写入操作主节点完全感知不到会直接造成主从两份数据不一致。因此线上环境建议不要关闭从节点只读模式。repl‑disable‑tcp‑nodelay 参数用来控制复制数据包发送策略适配不同的网络环境。参数默认为 no代表开启 TCP_NODELAY主节点不论数据包大小都会立刻发送给从节点主从延迟更低但会消耗更多带宽适合同机房部署场景。如果将参数设置为 yes主节点会合并细小的 TCP 数据包再发送节省网络带宽但会增大主从之间的数据同步延迟这种配置更适合跨机房部署的场景。三、三大复制拓扑结构Redis 的主从复制支持单层与多层的复制关系一共提供三种典型拓扑结构分别是一主一从、一主多从以及树形主从结构不同拓扑对应不同的业务使用场景。3.1. 一主一从一主一从是实现起来最简单的复制拓扑结构该架构主要用于主节点宕机之后依靠从节点提供故障转移的基础支持。当业务写并发较高同时又需要开启持久化保障数据安全时可以只在从节点开启 AOF 持久化。这样既可以保障数据不丢失还能够避免持久化操作给主节点带来磁盘性能上的压力。需要特别注意如果主节点关闭了持久化功能一旦主节点发生宕机要禁止主节点自动重启防止出现数据丢失的问题。3.2. 一主多从一主多从也叫作星形结构这种架构可以让业务系统借助多个从节点完成读写分离。在读请求占比很高的业务场景中可以把读请求负载均衡分发到各个从节点以此分担整体的查询压力。对于一些执行耗时比较久的读命令还可以专门指定某一台从节点去执行避免慢查询影响整个集群的运行稳定性。但该模式也存在明显短板当写并发量很高的时候主节点需要把写命令逐一发送给每一个从节点会加重主节点的 CPU 与网络负载。3.3. 树形主从树形主从结构也叫分层结构该模式下从节点不只是单纯复制顶层主节点的数据还可以充当其他从节点的主节点继续向下完成数据复制。架构中引入中间复制层之后可以有效降低顶层主节点的负载减少主节点向外传输的数据量。例如数据写入顶层 A 节点会同步给 B、C 两个从节点B 节点再进一步把数据同步给下层的 D、E 节点。当业务需要挂载数量非常多的从节点时为了避免大量同步操作拖累顶层主节点性能就适合采用这种树形拓扑。四、复制底层原理4.1. 建立复制主从复制的完整运行链路由从节点主动发起整体分为连接建立、数据同步、持续保活三大阶段通过六个标准化步骤完成全链路搭建与数据对齐。最开始是信息保存阶段当从节点配置了主节点地址后只会先在本地记录主节点的 IP 与端口信息此时主从物理连接尚未建立从节点的连接状态显示为 down。紧接着从节点内部的定时任务会每秒检测主节点配置一旦发现存在待连接的主节点就会主动发起 TCP 网络连接如果连接失败定时任务会持续重试直到连接成功或者用户取消复制配置。TCP 连接成功之后依次进入存活校验与权限验证环节。从节点会先向主节点发送 PING 命令在应用层确认主节点服务状态正常。如果 PING 超时未收到 PONG 响应从节点会主动断开连接等待下一轮定时任务重连。PING 校验通过后进入权限验证环节如果主节点配置了 requirepass 访问密码从节点就会用本地配置的 masterauth 密码进行鉴权密码验证失败的话复制流程会直接终止。鉴权通过后就进入核心的数据同步环节这也是整个复制流程中耗时最长的步骤。Redis 采用 PSYNC 命令完成数据同步替代了早期阻塞式的 SYNC 命令支持全量复制和部分复制两种模式。PSYNC 命令依赖两个核心标识来判断数据状态一个是 replicationid 复制 ID每个主节点启动或者从节点晋升为主时都会生成唯一的复制 ID节点会保存两组复制 ID用于网络抖动后恢复旧主连接另一个是 offset 复制偏移量主从节点各自累加记录已同步命令的字节长度从节点每秒会向主节点上报自身偏移量当两个节点的复制 ID 和偏移量完全一致时代表两份数据完全相同。从节点发起 PSYNC 请求后主节点会根据请求参数和自身缓冲区情况返回三种结果。返回 FULLRESYNC 代表需要执行全量复制一般出现在首次建立连接、或者从节点缺失数据超出缓冲区范围的场景返回 CONTINUE 代表可以执行部分复制仅补发缺失的增量数据返回 - ERR 则代表主节点版本过低不支持 PSYNC 命令需要降级为旧版 SYNC 命令完成全量同步。正常情况下 PSYNC 由 Redis 自动调用无需手动执行。4.2. 全量复制全量复制是主从首次建立连接时的必经阶段整体资源开销较高。整个流程从从节点发送 PSYNC ? -1 发起全量同步请求开始主节点收到后回复 FULLRESYNC同时后台执行 bgsave 生成 RDB 快照文件。生成的 RDB 文件会通过网络传输给从节点在 RDB 生成到传输完成的这段时间里主节点新增的写命令会暂存到复制缓冲区中等 RDB 传输结束后一并补发。从节点收到完整数据后会先清空本地旧数据再加载 RDB 文件恢复数据如果从节点开启了 AOF 持久化加载完成后还会自动执行 bgrewriteaof 优化 AOF 文件。全量复制也支持无磁盘模式2.8.18 版本之后可以开启 diskless 配置RDB 数据不落地直接通过网络发送省去磁盘读写的额外开销。4.3. 部分复制部分复制是针对全量复制高开销的优化方案主要用于处理网络短暂闪断的场景。它的实现依赖主节点上的复制积压缓冲区这是一个默认 1MB 的环形队列只有当存在连接的从节点时才会创建主节点所有写命令都会同时写入这个缓冲区。当主从网络中断重连后从节点会携带本地保存的复制 ID 和偏移量发起 PSYNC 请求主节点校验偏移量在缓冲区范围内后就会返回 CONTINUE仅补发中断期间缺失的命令以此用极小的开销完成数据对齐。如果缺失数据已经超出缓冲区覆盖范围还是会降级为全量复制。4.4. 实时复制 心跳检测完成初始数据同步之后主从进入实时复制与心跳保活阶段。主节点会通过 TCP 长连接源源不断地将所有写操作命令推送给从节点从节点逐条执行保证数据实时一致。为了维护长连接的健康状态主从之间采用应用层心跳机制双向检测主节点默认每 10 秒向从节点发送 PING 命令检测从节点存活状态从节点默认每 1 秒向主节点发送 replconf ack 命令上报自身当前的复制偏移量。如果主节点超过 repl-timeout 默认 60 秒未收到从节点响应就会判定从节点下线断开复制连接待从节点恢复连接后再重新进入同步流程。