Redis:不只是缓存那么简单(十六)

专栏:Redis 修行录

个人主页:手握风云

目录

一、主从复制概述

[1.1. 核心作用](#1.1. 核心作用)

[1.2. 主从节点规则](#1.2. 主从节点规则)

二、复制配置

三、三大复制拓扑结构

[3.1. 一主一从](#3.1. 一主一从)

[3.2. 一主多从](#3.2. 一主多从)

[3.3. 树形主从](#3.3. 树形主从)

四、复制底层原理

[4.1. 建立复制](#4.1. 建立复制)

[4.2. 全量复制](#4.2. 全量复制)

[4.3. 部分复制](#4.3. 部分复制)

[4.4. 实时复制 + 心跳检测](#4.4. 实时复制 + 心跳检测)


一、主从复制概述

1.1. 核心作用

在分布式系统当中,为了解决服务单点故障的风险,通常会把同一份数据生成多个副本,部署到多台不同的服务器上,以此实现故障恢复与负载均衡的能力。Redis 的主从复制就是基于这一思想设计的数据副本机制,可以为同一份数据维护多个 Redis 副本实例。

主从复制是 Redis 实现高可用的底层基础,哨兵、Redis 集群这些高可用方案,全部都是构建在主从复制能力之上。主从复制最核心要解决两类现实问题,一是单 Redis 节点的单点故障问题,单个节点宕机就会造成服务不可用;二是单节点的性能瓶颈问题,单台机器的 CPU、内存、网络资源有限,读写并发能力存在上限。

1.2. 主从节点规则

参与复制的 Redis 实例划分为主节点 master 与从节点 slave 两种角色。角色之间存在明确约束:每一个从节点只能够绑定唯一的一个主节点,但是一个主节点可以同时挂载若干个从节点。数据复制的数据流具备单向性,数据只能由主节点流向从节点,从节点的数据变更无法反向同步回主节点。

借助主从复制架构,可以实现读写分离的业务模式。业务写请求全部交给主节点处理,读请求可以分发到各个从节点执行,以此分担主节点的访问压力。但原生的主从复制存在明显短板,当主节点发生故障宕机的时候,从节点不会自动升级成为新的主节点,故障恢复需要人工介入操作,这也是后续哨兵机制需要解决的核心痛点。

二、复制配置

Redis 搭建主从复制,所有配置修改的均只针对从节点,主节点不需要做任何配置改动。

首先复制一份 Redis 原生配置文件,作为从节点专属配置文件,修改配置文件将 daemonize 设置为 yes,开启后台守护进程模式,端口号自定义。随后以独立端口启动从节点实例,通过启动参数指定主节点的地址与端口。

bash 复制代码
cp /etc/redis.conf ./slave1.conf
cp /etc/redis.conf ./slave2.conf
bash 复制代码
# 启动多个实例
redis-server ./slave1.conf
redis-server ./slave2.conf

此时的 3 个 Redis 实例还只是各自为政,没有构成主从关系。修改从节点配置文件,写入 slaveof 主节点IP 主节点端口,Redis 重启之后复制关系自动生效。

实例启动成功后,使用 redis‑cli 分别连接主节点与从节点。在主节点执行写入命令,就能够观察到数据会自动同步到从节点,以此验证主从复制链路工作正常。

bash 复制代码
redis-cli -p 6379
redis-cli -p 6380

如果想要查看主从复制的详细运行状态,可以执行 info replication 指令,这条命令会输出大量复制相关统计字段。

除了建立复制关系,slaveof 命令还可以完成断开复制与切换主节点的操作。在从节点执行 slaveof no one,就会断开和原有主节点之间的复制关系,同时该从节点晋升成为独立的主节点。执行该操作之后,从节点本地已经拥有的数据不会被清除,只是不再接收原主节点后续同步过来的新数据。

生产环境下还需要关注安全性、只读、网络延迟三类配置。当主节点配置requirepass访问密码时,从节点必须配置 masterauth 参数,参数值和主节点密码保持一致,否则从节点无法完成鉴权,复制流程会直接中断。

从节点默认开启 slave‑read‑only=yes 只读配置。由于复制数据流只能单向由主流向从,从节点发生写入操作,主节点完全感知不到,会直接造成主从两份数据不一致。因此线上环境建议不要关闭从节点只读模式。

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 秒未收到从节点响应,就会判定从节点下线,断开复制连接;待从节点恢复连接后,再重新进入同步流程。

相关推荐
驾驭人生17 小时前
Hangfire.Redis.StackExchange 已归档停更!生产任务卡死、重复执行、网络抖动问题解决方案
数据库·redis·缓存
TDengine (老段)19 小时前
TDengine Catalog 与元数据缓存
大数据·数据库·物联网·缓存·时序数据库·tdengine
hui-梦苑1 天前
[Gromacs]核心性能梯度测试:GROMACS 多线程性能调优实验
缓存·性能优化·多线程·gromacs·动力学模拟
Lyyaoo.1 天前
【链表】【中等】两数相加/倒N删除/两个交换/排序链表/LRU缓存
数据结构·链表·缓存
努力努力再努力wz1 天前
【Redis入门系列】:从 RESP 协议到 redis-plus-plus:Redis 客户端编程与 C++ 接口设计
开发语言·数据库·c++·redis·分布式·缓存·架构
OH_TPC2 天前
【鸿蒙优选三方库】@react-native-ohos/react-native-fast-image:高性能图片加载与缓存组件
缓存·华为·harmonyos·鸿蒙
liangshanbo12152 天前
手写 Event Emitter(事件发射器)
缓存
数智启示录2 天前
Apache Kafka Consumer 扩到 40 个仍不提速:Partition 上限锁死有效并行度 【Kafka合集】
数据库·经验分享·分布式·缓存·面试·kafka·apache
2601_962297252 天前
python自带缓存lru_cache用法及扩展的使用_python
python·缓存·装饰器·lru_cache·my_cache