NoSQL数据库Redis(三):主从复制

Redis 主从复制详解

Redis 主从复制 (Replication) 是 Redis 实现高可用性 (High Availability)、数据冗余备份以及读写分离的核心机制之一。它允许一个 Redis 服务器(称为主节点 ,Master)将其数据实时或准实时地复制到一个或多个其他 Redis 服务器(称为从节点,Slave 或 Replica)。这种机制极大地增强了 Redis 的健壮性和扩展性。

一、 主从复制的结构

在 Redis 主从复制结构中,存在明确的角色划分:

  1. 主节点 (Master)

    • 唯一可写的节点:所有写操作(如 SET, DEL, INCR 等)必须发送到主节点执行。
    • 数据变更的源头:主节点负责处理客户端写请求,并将数据变更通过复制机制传播给所有从节点。
    • 可以连接多个从节点:一个主节点可以同时拥有多个从节点。
  2. 从节点 (Replica / Slave)

    • 只读节点(默认):通常情况下,从节点仅处理客户端的读请求(如 GET, HGET, LRANGE 等)。这是实现读写分离的基础。
    • 数据同步目标:从节点会连接到指定的主节点,并复制主节点的所有数据。
    • 可级联复制:一个从节点自身也可以作为其他从节点的主节点,形成树状或链状的复制结构(但通常不建议层级过深)。
    • 数据备份:从节点持有主节点数据的完整副本,是天然的备份节点。

结构示意图

复制代码
          +-----------------+        +-----------------+        +-----------------+
          |                 |        |                 |        |                 |
Client -->|   Master Node   |<-------| Replica Node 1  |<-------| Replica Node 3  |
(Writes)  | (Writable)      |        | (Read-Only)     |        | (Read-Only)     |
          |                 |--------|                 |        |                 |
          +-----------------+        +-----------------+        +-----------------+
                          |                       ^
                          |                       |
                          v                       |
                    +-----------------+           |
                    |                 |           |
                    | Replica Node 2  |-----------+
                    | (Read-Only)     |
                    |                 |
                    +-----------------+

在这个结构中:

  • 客户端将所有写请求发送到 Master。
  • 客户端可以将读请求分发到 Master 或任意一个 Replica (实现读写分离)。
  • Replica 1 和 Replica 2 直接复制 Master 的数据。
  • Replica 3 复制 Replica 1 的数据(级联复制)。

二、 主从复制的原理

Redis 主从复制的工作过程主要分为两个阶段:初始化同步命令传播

1. 初始化同步 (Initial Synchronization)

当一个新从节点启动或首次连接到主节点时,需要获取主节点数据的完整副本。这个过程称为初始化同步或全量同步。

步骤详解

  1. 从节点连接主节点 :从节点通过配置(replicaof <masterip> <masterport>slaveof <masterip> <masterport>)连接到主节点,并发送 PSYNC 命令请求同步。
  2. 主节点生成 RDB 快照 :主节点接收到 PSYNC 命令后,如果判断需要进行全量复制(例如,从节点是首次连接,或者复制偏移量不匹配),主节点会调用 BGSAVE 命令在后台生成一个 RDB 文件快照。生成 RDB 期间,主节点继续处理写命令。
  3. 主节点发送 RDB 文件:RDB 文件生成完成后,主节点将其发送给从节点。从节点会清空自己的旧数据,然后加载接收到的 RDB 文件来初始化自己的数据集。
  4. 主节点发送复制缓冲区命令 :在生成和发送 RDB 文件期间,主节点处理的所有写命令 会被记录在一个内存缓冲区中(称为复制积压缓冲区,Replication Backlog Buffer)。RDB 文件发送完成后,主节点会将这些缓冲区中的写命令发送给从节点执行。这一步确保了从节点在加载完 RDB 后,能追赶上主节点在生成 RDB 期间的最新数据状态。
  5. 进入命令传播阶段:完成上述步骤后,从节点的数据与主节点在开始生成 RDB 那一刻的数据保持一致。之后,主节点进入命令传播阶段,持续将后续接收到的写命令发送给从节点执行。

关键点

  • 初始化同步期间主节点需要生成 RDB,可能耗费较多 CPU 和 I/O 资源,并占用网络带宽传输 RDB 文件。
  • 复制积压缓冲区 (repl-backlog-size) 的大小配置很重要。如果缓冲区太小,在同步慢或断线重连时,可能因为缓冲区被覆盖而被迫再次进行全量同步。

2. 命令传播 (Command Propagation)

初始化同步完成后,主从节点进入命令传播阶段。在这个阶段,主节点会将其接收到的每一个写命令,以 Redis 协议的形式,异步地发送给所有连接的从节点执行。

  • 异步复制:主节点在自身执行完写命令后,会将该命令放入发送队列,然后立即响应客户端。命令的发送和从节点的执行是异步进行的。这意味着存在一个非常短暂的时间窗口(通常毫秒级),主节点的数据可能比从节点更新。这是 Redis 复制最终一致性的体现。
  • 增量复制:命令传播阶段就是增量复制的过程,每次只同步变更的命令。
  • 复制偏移量 (Replication Offset)
    • 主节点和每个从节点都维护一个复制偏移量。
    • 主节点每发送一个字节的数据(命令)给从节点,主节点的复制偏移量就会增加。
    • 从节点每接收并执行一个字节的数据(命令),从节点的复制偏移量就会增加。
    • 通过比较主从节点的复制偏移量,可以判断它们的数据是否一致。INFO replication 命令可以查看偏移量信息。
  • 复制 ID (Replication ID):主节点启动时会生成一个唯一的复制 ID。这个 ID 与复制偏移量一起,用于标识一个特定的数据历史版本。当主节点重启(如故障切换后),复制 ID 会改变。

3. 部分重同步 (Partial Resynchronization)

当网络发生短暂中断或从节点短暂重启后重新连接主节点时,如果条件满足,Redis 会尝试进行部分重同步,避免代价高昂的全量同步。

前提条件

  • 从节点保存了之前连接主节点的复制 ID (master_replid) 和复制偏移量 (master_repl_offset)。
  • 主节点当前的复制 ID 没有改变(即主节点没有发生故障切换)。
  • 从节点断开期间丢失的数据(即从节点记录的 master_repl_offset 之后的数据)仍然存在于主节点的复制积压缓冲区中。

过程

  1. 从节点重新连接主节点,发送 PSYNC <replid> <offset> 命令,带上自己记录的复制 ID 和偏移量。
  2. 主节点检查:
    • 收到的复制 ID 是否与自己的当前复制 ID 匹配。
    • 请求的偏移量之后的数据是否还在自己的复制积压缓冲区中。
  3. 如果条件满足,主节点回复 CONTINUE,表示可以进行部分重同步。然后主节点将复制积压缓冲区中从请求偏移量开始的所有数据发送给从节点。
  4. 从节点接收并执行这些命令,从而将数据同步到最新状态。
  5. 之后进入正常的命令传播阶段。

如果条件不满足(例如主节点复制 ID 变了,或者请求偏移量之前的数据已被覆盖),则主节点会回复 FULLRESYNC <replid> <offset>,触发一次全量同步。

三、 主从复制的配置管理 (OpenEuler)

在 OpenEuler 系统上配置 Redis 主从复制,主要涉及修改 Redis 的配置文件 redis.conf。以下列出关键配置项及其含义:

1. 主节点配置 (Master)

主节点的配置通常相对简单,主要是确保其可以接受连接并设置密码(如果需要认证)。关键配置项:

  • bind 0.0.0.0bind <specific_ip>:指定 Redis 监听的网络接口。0.0.0.0 表示监听所有接口(生产环境建议绑定具体 IP)。
  • port 6379:监听端口,默认 6379。
  • requirepass <password>:设置主节点的访问密码。强烈建议设置强密码。从节点连接时需要用到这个密码。
  • masterauth <password>如果主节点自身也是另一个主节点的从节点(级联复制),则需要设置此项为它的主节点的密码。在纯主节点角色下,此项不需要配置。
  • maxmemory <bytes>:设置最大内存限制,根据服务器内存情况配置,避免 OOM。
  • repl-backlog-size <size>:设置复制积压缓冲区大小。默认 1mb。在断线重连频繁或网络不稳定的场景下,建议增大此值 (例如 128mb256mb),以减少全量同步的概率。值越大,占用的内存越多。
  • repl-backlog-ttl <seconds>:设置复制积压缓冲区在没有从节点连接时的存活时间。默认 3600 秒(1小时)。超过此时间且无从节点连接,缓冲区会被释放。
  • repl-diskless-sync <yes|no>:是否使用无盘同步。默认 no。设置为 yes 时,主节点在初始化同步时直接将 RDB 内容通过 Socket 发送给从节点,而 先将 RDB 写入磁盘。这可以节省 I/O 和磁盘空间,但会消耗更多网络带宽。仅在网络速度非常快且磁盘 I/O 是瓶颈时才考虑启用
  • repl-diskless-sync-delay <seconds>:无盘同步时,等待更多从节点加入一起同步的延迟时间(秒)。默认 5。可以分摊主节点生成 RDB 的负载。

2. 从节点配置 (Replica)

从节点需要明确指定其主节点。关键配置项:

  • replicaof <masterip> <masterport>slaveof <masterip> <masterport>:指定主节点的 IP 地址和端口。例如 replicaof 192.168.1.100 6379。这是配置从节点的核心指令
  • masterauth <password>:设置用于连接主节点所需的密码。这个密码必须和主节点 requirepass 设置的密码一致。
  • replica-read-only yes:设置从节点是否为只读模式。默认 yes强烈建议保持只读,除非有特殊需求。
  • repl-diskless-load <disabled|swapdb|on-start>:从节点在加载初始化同步的 RDB 时使用的策略。默认 disabled(使用磁盘加载)。swapdb 在加载时保持旧数据库可用(需要额外内存),on-start 尝试从 Socket 直接加载(需要 repl-diskless-sync yes 且主节点支持)。一般保持默认 disabled 即可
  • 其他配置如 bind, port, requirepass(用于保护从节点自身连接)等也需要根据实际情况配置。

配置生效 :修改配置文件后,需要重启 Redis 服务使配置生效。OpenEuler 上通常使用 systemctl

bash 复制代码
sudo systemctl restart redis
# 或者指定配置文件路径,如果使用了非默认路径
sudo redis-server /path/to/redis.conf

查看复制状态 :使用 redis-cli 连接 Redis 实例,执行 INFO replication 命令可以获取详细的复制信息,包括角色、连接状态、复制 ID、偏移量、从节点列表等。

四、 部署 Redis 主从复制实例 (OpenEuler)

假设我们有 3 台 OpenEuler 服务器:

  • master-node (IP: 192.168.1.100) - 主节点
  • replica-node1 (IP: 192.168.1.101) - 从节点 1
  • replica-node2 (IP: 192.168.1.102) - 从节点 2

步骤 1:安装 Redis

在所有三台服务器上安装 Redis。OpenEuler 通常可以通过 dnf 安装:

bash 复制代码
sudo dnf install redis -y

安装完成后,默认配置文件位于 /etc/redis.conf

步骤 2:配置主节点 (master-node)

编辑 /etc/redis.conf

bash 复制代码
sudo vim /etc/redis.conf

找到并修改以下配置项:

bash 复制代码
# 绑定地址 (根据实际情况修改)
bind 0.0.0.0  # 或 bind 192.168.1.100
port 6379
# 设置密码 (替换 your_strong_password)
requirepass your_strong_password
# 可选:增大复制积压缓冲区
repl-backlog-size 128mb
# 可选:禁用保护模式 (如果 bind 0.0.0.0 且不设密码,生产环境不建议)
# protected-mode no  # 仅在测试或安全网络环境中谨慎使用
# 确保 daemonize yes (后台运行)
daemonize yes
# 设置日志文件
logfile /var/log/redis/redis.log
# 设置数据目录
dir /var/lib/redis

保存并退出。

创建日志和数据目录(如果不存在):

bash 复制代码
sudo mkdir -p /var/log/redis /var/lib/redis
sudo chown redis:redis /var/log/redis /var/lib/redis  # 确保 Redis 用户有权限

启动 Redis 服务:

bash 复制代码
sudo systemctl enable redis --now
sudo systemctl status redis  # 检查状态是否 active (running)

步骤 3:配置从节点 (replica-node1replica-node2)

分别在两台从节点服务器上编辑 /etc/redis.conf

bash 复制代码
vim /etc/redis.conf

修改以下配置项:

bash 复制代码
bind 0.0.0.0  # 或绑定具体 IP
port 6379
# 指定主节点和密码 (替换 master_ip, master_port, master_password)
replicaof 192.168.1.100 6379
masterauth your_strong_password  # 必须与主节点的 requirepass 一致
# 保持只读
replica-read-only yes
# 设置从节点自身密码 (可选,保护从节点连接)
requirepass replica_strong_password  # 如果设置,客户端连接从节点时需要此密码
# 同样配置日志、数据目录等
daemonize yes
logfile /var/log/redis/redis.log
dir /var/lib/redis

保存并退出。

创建目录并设置权限:

bash 复制代码
sudo mkdir -p /var/log/redis /var/lib/redis
sudo chown redis:redis /var/log/redis /var/lib/redis

启动 Redis 服务:

bash 复制代码
sudo systemctl enable redis --now
sudo systemctl status redis

步骤 4:验证主从复制

  1. 连接主节点 :在 master-node 或任何能访问主节点的机器上使用 redis-cli

    bash 复制代码
    redis-cli -h 192.168.1.100 -a your_strong_password

    执行命令:

    redis 复制代码
    INFO replication

    查看输出:

    • role:master 确认角色。
    • connected_slaves:2 应该显示已连接的从节点数量。
    • slave0slave1 部分,可以看到从节点的 IP、端口、状态 (online)、复制偏移量等信息。
  2. 连接从节点:连接其中一个从节点:

    bash 复制代码
    redis-cli -h 192.168.1.101 -a your_strong_password  # 或用从节点自身密码

    执行:

    redis 复制代码
    INFO replication

    查看输出:

    • role:slave 确认角色。
    • master_host:192.168.1.100, master_port:6379 确认连接的主节点。
    • master_link_status:up 表示连接正常。
    • master_last_io_seconds_ago 值很小(通常 0 或 1)表示最近有通信。
    • master_sync_in_progress:0 表示当前没有在进行全量同步。
    • 比较 master_repl_offset 和主节点上看到的对应从节点的 slave_repl_offset,它们应该非常接近(最终一致)。
  3. 测试数据同步

    • 在主节点上写入数据:

      redis 复制代码
      SET master_key "Hello from Master"
    • 在任意从节点上读取该数据:

      redis 复制代码
      GET master_key  # 应返回 "Hello from Master"
    • 尝试在从节点上写入:

      redis 复制代码
      SET slave_key "Try write"  # 应该会报错:(error) READONLY You can't write against a read only replica.

      验证了从节点的只读属性。

步骤 5:模拟故障转移 (高级)

  1. 主节点宕机 :手动停止主节点的 Redis 服务 (master-node):

    bash 复制代码
    sudo systemctl stop redis
  2. 观察从节点 :连接一个从节点,执行 INFO replication

    • master_link_status:down 表示连接断开。
    • 客户端对从节点的读请求可能还能成功(取决于数据是否最新),但无法写入
  3. 手动切换主节点 :选择一个从节点(如 replica-node1)提升为新的主节点:

    • 连接到该从节点:

      bash 复制代码
      redis-cli -h 192.168.1.101 -a your_strong_password
    • 执行命令使其停止复制并成为主节点:

      redis 复制代码
      REPLICAOF NO ONE  # 或 SLAVEOF NO ONE
    • 验证:

      redis 复制代码
      INFO replication  # role 应变为 master
  4. 重新配置其他从节点 :将另一个从节点 (replica-node2) 指向新的主节点 (192.168.1.101):

    • 连接到 replica-node2

      bash 复制代码
      redis-cli -h 192.168.1.102 -a your_strong_password
    • 执行:

      redis 复制代码
      REPLICAOF 192.168.1.101 6379
    • 验证 INFO replication 显示新的主节点信息且状态 up

  5. 恢复原主节点 :如果原主节点恢复,可以将其配置为当前新主节点 (192.168.1.101) 的从节点,或者根据需要进行其他处理。

注意 :上述步骤 5 是手动故障转移。在生产环境中,通常使用 Redis SentinelRedis Cluster 来实现自动化的高可用和故障转移,避免人工干预。

五、 总结与注意事项

Redis 主从复制是构建高可用 Redis 架构的基础。在 OpenEuler 系统上部署时,需注意:

  1. 安全性 :务必为主节点和从节点设置强密码 (requirepass),并在从节点配置 masterauth。避免使用 protected-mode no 暴露无密码实例到公网。
  2. 配置优化 :根据网络和负载情况调整 repl-backlog-size。谨慎使用无盘复制 (repl-diskless-sync)。
  3. 监控 :定期使用 INFO replication 监控主从状态、偏移量差异和连接健康状况。
  4. 只读从节点 :保持 replica-read-only yes 是标准做法,除非有特殊需求。
  5. 高可用 :主从复制本身不提供自动故障转移。对于生产环境,强烈建议结合 Redis Sentinel 或 Redis Cluster 来实现主节点故障时的自动切换,保证服务连续性。
  6. 持久化:主从复制不是备份的替代品。仍然需要在主节点(或从节点)配置适当的 RDB 或 AOF 持久化策略,防止数据丢失。
  7. 网络:确保主节点和从节点之间的网络通信畅通且延迟低,以保证复制的实时性。
相关推荐
IT大白鼠1 天前
Redis 系列 · 第 01 篇——认知入门:Redis 是什么
redis·nosql
彧azz1 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
lbb 小魔仙1 天前
OpenClaw + cpolar 实战:远程 NAS、分享小游戏、RDP,再配置公网 AI 入口
数据库·人工智能·redis·oracle·prometheus
夕除2 天前
redis--018
redis
两锭子2 天前
Redis基础
redis
烟沙九洲2 天前
Redis 缓存穿透、缓存击穿、缓存雪崩
数据库·redis
字节探索2 天前
Redis 只会当缓存用?这 10 大实战场景,让你的系统快到飞起
redis·后端
于樱花森上飞舞2 天前
【Redis】哨兵详解
java·开发语言·数据库·redis
Rain的Java大神之路2 天前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
Wang's Blog2 天前
Java 接入Redis: 通用命令与键管理
java·服务器·redis