【Redis 进阶】主从复制深度解析:从配置落地到 PSYNC 同步原理


🔥草莓熊Lotso: 个人主页
❄️个人专栏: 《C++知识分享》 《Linux 入门到实践:零基础也能懂》
✨生活是默默的坚持,毅力是永久的享受!


🎬 博主简介:


文章目录

  • 前言:
  • [一. 认识主从复制](#一. 认识主从复制)
    • [1.1 核心概念](#1.1 核心概念)
    • [1.2 解决的两个核心问题](#1.2 解决的两个核心问题)
  • [二. 主从复制配置与基础操作](#二. 主从复制配置与基础操作)
    • [2.1 启动多实例](#2.1 启动多实例)
    • [2.2 建立主从关系](#2.2 建立主从关系)
    • [2.3 查看主从状态](#2.3 查看主从状态)
    • [2.4 断开与切换主从](#2.4 断开与切换主从)
    • [2.5 安全、只读与传输优化](#2.5 安全、只读与传输优化)
  • [三. 主从复制的拓扑结构](#三. 主从复制的拓扑结构)
    • [3.1 一主一从](#3.1 一主一从)
    • [3.2 一主多从](#3.2 一主多从)
    • [3.3 树形结构](#3.3 树形结构)
  • [四. 主从复制的完整建立流程](#四. 主从复制的完整建立流程)
  • [五. PSYNC 同步协议](#五. PSYNC 同步协议)
    • [5.1 两个核心标识](#5.1 两个核心标识)
    • [5.2 PSYNC 的三种响应](#5.2 PSYNC 的三种响应)
  • [六. 三种复制模式详解](#六. 三种复制模式详解)
    • [6.1 全量复制](#6.1 全量复制)
    • [6.2 部分复制](#6.2 部分复制)
    • [6.3 实时复制](#6.3 实时复制)
  • [七. 主从复制小结与常见问题](#七. 主从复制小结与常见问题)
    • [7.1 优缺点总结](#7.1 优缺点总结)
    • [7.2 关于从节点晋升](#7.2 关于从节点晋升)
    • [7.3 常见排坑:多实例启动失败](#7.3 常见排坑:多实例启动失败)
  • 结尾:

前言:

单机 Redis 虽然性能强劲,但天然存在两个无法回避的短板:一是单点故障,机器宕机则服务完全中断;二是性能上限,单节点能承载的读并发终究有瓶颈。主从复制就是解决这两个问题的基础方案:通过数据多副本实现读写分离,同时为后续的故障转移打下基础。很多开发者配置主从只会在配置文件加一行 slaveof,遇到主从不一致、频繁全量同步、复制延迟等问题时就无从下手。实际上主从复制背后有一套完整的机制:从初次全量同步到网络闪断后的部分续传,从积压缓冲区到心跳保活,每一环都有明确的设计逻辑。本文从基础概念与配置落地讲起,逐一拆解三种拓扑结构、完整同步流程、PSYNC 协议原理,以及全量、部分、实时三种复制模式的底层细节,最后结合源码视角与常见排坑,帮你把主从复制从「会配置」吃透到「懂原理、能排障」。


一. 认识主从复制

1.1 核心概念

主从模式下,Redis 节点分为两种角色:

  • 主节点(Master):负责处理所有写请求,也可以处理读请求;数据发生修改后,主动将变更同步给所有从节点。
  • 从节点(Slave):从主节点同步数据,默认只读,不可写入;对外提供读服务,分担主节点的读压力。

同步方向是单向的:只能从主节点同步到从节点,从节点的修改不会反向同步给主节点。也正因如此,默认从节点被配置为只读,避免人为写入造成主从数据不一致。

1.2 解决的两个核心问题

  1. 提升可用性 单节点挂了整个服务就不可用;主从架构下,单个从节点挂了不影响整体服务,主节点挂了也可以手动将从节点晋升为主节点,快速恢复服务。当然,原生主从模式不支持自动故障转移,需要人工干预,这也是后续哨兵机制要解决的问题。
  2. 提升读性能 实际业务中读请求量通常远大于写请求。通过多个从节点分担读流量,可以大幅提升整体的并发承载能力,实现读写分离。

注意:主从模式只能扩展读能力,无法扩展写能力。所有写请求仍然落在主节点上,写性能瓶颈仍然受限于单主节点。


二. 主从复制配置与基础操作

2.1 启动多实例

要搭建主从,首先要运行多个 Redis 实例。单机环境下通过不同端口区分,有两种配置方式:

  • 命令行启动时指定 --port 参数;
  • 为每个实例单独准备配置文件,修改 port 字段,更推荐也更规范。

以一主两从为例,主节点用默认 6379 端口,两个从节点分别用 6380、6381 端口,同时将 daemonize yes 设为后台运行。

2.2 建立主从关系

配置主从关系有三种方式,效果一致,生效周期不同:

  1. 配置文件(推荐,持久生效) 在从节点配置文件中加入:
    1.

    Plain 复制代码
    slaveof 127.0.0.1 6379
    1. 重启后永久生效,是生产环境的标准做法。
  2. 启动参数(临时) 启动时追加参数:redis-server --slaveof 127.0.0.1 6379

  3. 客户端命令(临时) 连接到从节点后直接执行:
    1.

    bash 复制代码
    127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
    OK
    1. 命令方式修改是即时生效的,但实例重启后会失效,回到配置文件中的设定。

2.3 查看主从状态

使用 INFO replication 命令可以查看完整的复制信息。

主节点视角:

bash 复制代码
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=1964,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=1964,lag=1
master_replid:0c19b3c9cce2038f85c077905a014a4f47e6282b
master_repl_offset:1964
repl_backlog_active:1
repl_backlog_size:1048576

关键字段含义:

  • role:当前节点角色;
  • offset:复制偏移量,代表数据同步进度;
  • replid:复制 ID,主节点身份标识;
  • repl_backlog:复制积压缓冲区,是部分复制的核心。

从节点视角可以看到主节点地址、连接状态、自身偏移量、只读开关等信息。

2.4 断开与切换主从

断开主从关系

在从节点执行 SLAVEOF NO ONE,即可断开与主节点的联系,晋升为独立的主节点。

bash 复制代码
127.0.0.1:6381> SLAVEOF no one
OK

断开后,从节点已有的数据不会清空,但不再接收主节点的新变更。

切换主节点

从节点也可以重新指定新的主节点,比如 SLAVEOF 127.0.0.1 6380,形成链式复制结构。注意命令行修改都是临时的,重启后会回到配置文件设定的状态。

2.5 安全、只读与传输优化

  1. 密码验证 如果主节点开启了 requirepass 密码,从节点需要配置 masterauth 参数填写相同密码,才能正常建立复制连接。
  2. 从节点只读 默认 slave-read-only yes,从节点禁止写入,避免人为造成主从不一致。生产环境不建议关闭这个选项。
  3. 传输延迟优化 主从同步基于 TCP 传输,涉及 Nagle 算法的取舍:
    1. 开启 Nagle:小数据包合并发送,节省带宽,但延迟更高;
    2. 关闭 Nagle:数据立即发送,延迟更低,但带宽消耗更大。
    3. 对应配置 repl-disable-tcp-nodelay,默认 no 即开启 Nagle。局域网延迟低的场景可以关闭以获得更快的同步速度;跨机房、带宽紧张的场景建议保持开启。

三. 主从复制的拓扑结构

根据业务规模和部署环境,主从复制有三种典型拓扑。

3.1 一主一从

最简单的结构,一个主节点带一个从节点。

  • 适用场景:数据量小、读压力低的基础业务,主要用于数据备份和基础容灾。
  • 优化技巧:可以关闭主节点的 AOF 持久化,只在从节点开启,降低主节点的磁盘 IO 压力。
  • ⚠️ 注意陷阱:如果主节点关闭了持久化,宕机后千万不要自动重启。否则主节点本地没有数据,启动后是空库,同步给从节点会把从节点的数据也清空,造成严重的数据丢失。

3.2 一主多从

一个主节点挂载多个从节点,是最经典的读写分离架构。

  • 适用场景:读请求量大,需要多个从节点分摊读流量。
  • 缺点:从节点数量越多,主节点的网络带宽压力越大,每个从节点都要单独接收一份完整的同步数据流。

3.3 树形结构

主节点只挂载少量二级从节点,二级从节点再挂载三级从节点,形成树状层级。

  • 优势:大幅降低主节点的网卡带宽压力,把同步压力分摊到中间层节点;适合节点数量多、跨机房部署的场景。
  • 劣势:层级越深,数据同步的延迟越高,最底层节点的数据滞后更明显。

四. 主从复制的完整建立流程

从从节点执行 slaveof 到数据完全同步,一共分为 6 个步骤:

  1. 保存主节点信息 从节点先把主节点的 IP 和端口记录下来,后续流程基于这个地址执行。
  2. 建立 TCP 连接 从节点主动向主节点发起 TCP 三次握手,建立长连接。这一步是系统层面的连通性验证。
  3. 发送 PING 命令 连接建立后,从节点发送 PING 命令,验证主节点服务正常可用、命令可以正常响应,相当于应用层的健康检查。
  4. 权限验证 如果主节点设置了密码,从节点携带 masterauth 配置的密码进行身份校验。
  5. 同步数据集 也就是全量复制阶段,主节点把完整的数据快照发给从节点,从节点清空旧数据加载新快照,完成数据初始化。
  6. 命令持续复制 全量同步完成后,进入增量实时同步阶段。主节点后续收到的所有写命令,都会异步发送给从节点执行,保持数据一致。

五. PSYNC 同步协议

Redis 使用 PSYNC 命令来完成数据同步,它替代了早期的 SYNC 命令,核心改进是支持部分复制,避免了网络闪断后就要重新全量同步的高昂开销。

5.1 两个核心标识

PSYNC 命令携带两个参数:replicationidoffset,共同定位从节点的同步状态。

replicationid(复制 ID)

  • 每个主节点启动时都会生成一个唯一的复制 ID,代表这一任主节点的数据版本;
  • 从节点和主节点建立复制关系后,会继承主节点的 replid;
  • 节点重启、从节点晋升为主节点时,都会生成新的 replid。
  • 除了主 replid,还有 replid2,用来记录上一任主节点的复制 ID。比如从节点临时升主后,还保留着旧主的 replid,后续网络恢复后可以重新接入旧主,做部分同步。

offset(复制偏移量)

  • 主从节点各自维护一个偏移量,本质是累计同步的字节数;
  • 主节点每处理一条写命令,就把命令的字节长度累加到自己的偏移量上;
  • 从节点每收到并执行一条同步命令,也累加自己的偏移量;
  • 从节点每秒会把自己的偏移量上报给主节点。

当两个节点 replid 相同、offset 也相同时,就认为两者数据完全一致。

5.2 PSYNC 的三种响应

从节点发送 PSYNC <replid> <offset> 后,主节点会根据自身状态返回三种结果:

  1. +FULLRESYNC <replid> <offset>:需要执行全量复制。初次同步、或者偏移量超出积压缓冲区范围时返回。
  2. +CONTINUE:可以执行部分复制,只补发缺失的增量数据。
  3. -ERR:主节点版本过低,不支持 PSYNC,从节点回退使用旧的 SYNC 命令做全量复制。

初次同步时,从节点不知道主节点的 replid,会发送 PSYNC ? -1,主动请求全量复制。


六. 三种复制模式详解

6.1 全量复制

全量复制是把主节点完整数据一次性同步给从节点,开销最大,一般用于初次建立复制的场景。

完整执行流程

  1. 从节点发送 PSYNC ? -1 请求全量同步;
  2. 主节点返回 +FULLRESYNC 响应,携带自己的 replid 和 offset;
  3. 主节点后台执行 bgsave,生成 RDB 快照文件;
  4. 生成 RDB 期间,主节点新收到的写命令会暂存到复制缓冲区中;
  5. RDB 生成完毕后,主节点把 RDB 文件发送给从节点;
  6. 从节点清空自身旧数据,加载 RDB 文件到内存;
  7. 加载完成后,主节点把缓冲区中暂存的写命令发给从节点执行,补齐 RDB 生成期间的增量数据;
  8. 如果从节点开启了 AOF,会自动触发一次 bgrewriteaof,生成最新的 AOF 文件。

无硬盘复制(diskless)

默认全量复制需要主节点先把 RDB 写入本地磁盘,再通过网络发给从节点。无硬盘模式下,主节点生成的 RDB 数据直接通过网络发送,省去本地磁盘读写的开销,适合磁盘 IO 紧张、网络带宽充足的场景。 但即使开启无硬盘模式,全量复制仍然是重量级操作,网络传输的开销是无法省略的。

6.2 部分复制

部分复制是 PSYNC 的核心价值,专门用来处理网络闪断场景:从节点短暂断开重连后,只补发缺失的那部分命令,不用重新全量同步。

核心依赖:复制积压缓冲区

主节点内部维护了一个固定大小的环形缓冲区(repl_backlog),默认 1MB,用来保存最近一段时间的写命令。

  • 它是一个先进先出的队列,新数据不断写入,旧数据不断被覆盖;
  • 大小由 repl_backlog_size 配置,设置得越大,能容忍的断网时间就越长。

执行流程

  1. 网络中断后,超过超时时间主节点会认为从节点下线,但仍然持续往积压缓冲区写入新的写命令;
  2. 网络恢复,从节点重新连接主节点,携带自己的 replid 和 offset 发送 PSYNC 请求;
  3. 主节点先校验 replid 是否一致,不一致直接走全量复制;
  4. replid 一致则检查 offset 是否还在积压缓冲区的范围内:
    1. 在范围内:返回 +CONTINUE,把 offset 之后的所有命令补发过去;
    2. 超出范围:缓冲区已经覆盖了旧数据,只能走全量复制。

这也是为什么生产环境建议适当调大 repl_backlog_size:可以显著降低网络抖动后触发全量复制的概率。

6.3 实时复制

全量同步完成、主从数据一致后,就进入长期的实时复制阶段。

  • 主从之间保持 TCP 长连接;
  • 主节点每收到一条写命令,就异步将命令转发给所有从节点;
  • 从节点接收并执行命令,维持与主节点的数据一致。

为了保证连接健康,双方通过心跳机制维持状态:

  • 主节点:默认每 10 秒向从节点发送 PING 心跳,连续 60 秒没收到回复就认为从节点下线;
  • 从节点:默认每秒向主节点上报自己的复制偏移量,同时相当于心跳。

树形拓扑下,数据要经过多层节点转发,延迟会逐层叠加;而一主多从结构下所有从节点的延迟都是一跳。

源码视角:主从复制的设计细节

  1. replid 与 runid 的区别

很多资料会把两个概念混为一谈,实际上它们是完全独立的两个 ID:

  • run_id:服务器运行 ID,每个节点启动时生成,主要供哨兵机制做节点身份识别,在 sentinel.c 中大量使用;
  • replid:复制 ID,主从复制体系的身份标识,定义在 redisServer 结构体中,在 replication.c 的同步逻辑里使用。

两者格式相似、长度相同,但职责不同,不要混淆。

  1. 复制积压缓冲区的环形设计

积压缓冲区本质是一个带读写指针的环形字符数组。主节点写入时移动写指针,超出缓冲区大小时覆盖最旧的数据;部分复制时根据从节点的 offset 计算起始位置,向后读取所有增量命令。 这种设计用固定的内存开销,换取了断网重连后的快速恢复,是非常经典的用空间换时间、用概率换成本的工程思路。

  1. 全量复制的缓冲区设计

全量复制期间,RDB 生成和传输都需要时间,这段时间的新写命令不能丢,也不能直接发给从节点(会打乱 RDB 加载的顺序)。 Redis 的做法是暂存到客户端输出缓冲区中,等从节点加载完 RDB 再统一发送。这也是主节点在全量同步期间内存会有一定上涨的原因。


七. 主从复制小结与常见问题

7.1 优缺点总结

优势

  1. 实现数据多副本,提升了数据可靠性;
  2. 支持读写分离,横向扩展读性能;
  3. 支持多种拓扑,可根据场景灵活选择。

局限

  1. 主节点是单点,宕机后需要人工干预切换,无法自动故障转移;
  2. 所有写请求都经过主节点,写能力无法横向扩展;
  3. 从节点数量越多、层级越深,同步延迟越明显。

7.2 关于从节点晋升

从节点成为主节点只有两种情况:

  1. 主动断开 :执行 SLAVEOF NO ONE,从节点主动脱离主节点,晋升为主节点;
  2. 主节点故障 :原生主从模式下,主节点挂了从节点不会自动晋升,必须人工操作切换。这也是引入哨兵机制的核心原因 ------ 自动完成故障转移。

7.3 常见排坑:多实例启动失败

同一台机器部署多个实例时,很容易踩一个坑:所有实例共用同一个工作目录 dir,导致 RDB、AOF 文件互相覆盖,还可能出现权限问题。 比如 root 用户手动启动的实例生成了 root 权限的 AOF 文件,再用 redis 用户通过服务启动时,因为没有写权限而启动失败。 标准解决方案:每个实例单独配置独立的工作目录,各自生成持久化文件,互不干扰。

核心考点总结

  1. 基础概念:主写从读、单向同步、从节点默认只读;解决读扩展与基础容灾,无法扩展写能力。
  2. 配置操作 :三种配置主从的方式;INFO replication 关键字段含义;SLAVEOF NO ONE 断开复制。
  3. 拓扑结构:一主一从、一主多从、树形结构的适用场景与优缺点;关闭主节点持久化的注意事项。
  4. 建立流程:保存信息 → 建连 → PING → 鉴权 → 全量同步 → 增量持续复制。
  5. PSYNC 协议:replid 标识数据版本,offset 标识同步进度;三种响应对应的同步模式。
  6. 复制模式
    1. 全量复制:bgsave 生成 RDB + 缓冲区补发增量,开销大,初次同步使用;
    2. 部分复制:基于环形积压缓冲区,网络闪断后补发缺失数据,核心优化点;
    3. 实时复制:长连接增量同步,心跳机制维持连接健康。
  7. 常见问题:主节点宕机不会自动切换;多实例需独立工作目录;replid 与 runid 的区别。

结尾:

html 复制代码
🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点:
👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长
❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量
⭐ 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用
💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑
🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解
技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标!

结语:主从复制是 Redis 高可用体系的第一块基石,它解决了数据多副本和读性能扩展的问题,但主节点单点故障的自动切换仍然是空白。也正是为了弥补这个短板,才有了哨兵(Sentinel)机制:自动监控主节点状态、故障时自动选举新主、完成地址切换。理解主从复制的底层原理,不仅能帮你排查日常的同步延迟、数据不一致问题,也为后续学习哨兵和集群打下扎实的基础。

✨把这些内容吃透超牛的!放松下吧✨ ʕ˘ᴥ˘ʔ づきらど

相关推荐
爱学习的程序媛1 小时前
TCP / UDP 协议详解
网络·网络协议·udp·tcp·通信协议
爱学习的程序媛1 小时前
以太网协议详解
网络·网络协议·计算机网络·以太网·ethernet·通信协议
兔叭_哥1 小时前
WPS 阿里V3 全流程逆向分析与求解
网络·wps
比兔代理1 小时前
代理 IP 延迟优化全链路:从节点选型、TCP 参数到协议栈调优
网络·http·ip
Joy T1 小时前
Spring AI 2.0 进阶入门:Workflow、Routing、Task State 与可控 Agent
开发语言·人工智能·workflow·routing·springai·orchestrator·evaluator
YangYang9YangYan1 小时前
2026 校招市场数据分析 JD 拆解,SQL 要求、工具与面试考点
数据库·人工智能·数据分析
重生之小比特1 小时前
【Java SE】抽象类和接口
java·开发语言
传奇开心果编程1 小时前
【Rust入门知识点学与练】第33课:异步编程入门(async/await)强化
开发语言·学习·rust
终端安全笔记1 小时前
iOS 27 强制 TLS 1.2:租赁设备的注册链路会在哪一环断
android·网络·安全·ios·智能手机