NoSQL数据库Redis(三):主从复制
Redis 主从复制详解Redis 主从复制 (Replication) 是 Redis 实现高可用性 (High Availability)、数据冗余备份以及读写分离的核心机制之一。它允许一个 Redis 服务器称为主节点Master将其数据实时或准实时地复制到一个或多个其他 Redis 服务器称为从节点Slave 或 Replica。这种机制极大地增强了 Redis 的健壮性和扩展性。一、 主从复制的结构在 Redis 主从复制结构中存在明确的角色划分主节点 (Master)唯一可写的节点所有写操作如SET,DEL,INCR等必须发送到主节点执行。数据变更的源头主节点负责处理客户端写请求并将数据变更通过复制机制传播给所有从节点。可以连接多个从节点一个主节点可以同时拥有多个从节点。从节点 (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)当一个新从节点启动或首次连接到主节点时需要获取主节点数据的完整副本。这个过程称为初始化同步或全量同步。步骤详解从节点连接主节点从节点通过配置replicaof masterip masterport或slaveof masterip masterport连接到主节点并发送PSYNC命令请求同步。主节点生成 RDB 快照主节点接收到PSYNC命令后如果判断需要进行全量复制例如从节点是首次连接或者复制偏移量不匹配主节点会调用BGSAVE命令在后台生成一个 RDB 文件快照。生成 RDB 期间主节点继续处理写命令。主节点发送 RDB 文件RDB 文件生成完成后主节点将其发送给从节点。从节点会清空自己的旧数据然后加载接收到的 RDB 文件来初始化自己的数据集。主节点发送复制缓冲区命令在生成和发送 RDB 文件期间主节点处理的所有写命令会被记录在一个内存缓冲区中称为复制积压缓冲区Replication Backlog Buffer。RDB 文件发送完成后主节点会将这些缓冲区中的写命令发送给从节点执行。这一步确保了从节点在加载完 RDB 后能追赶上主节点在生成 RDB 期间的最新数据状态。进入命令传播阶段完成上述步骤后从节点的数据与主节点在开始生成 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之后的数据仍然存在于主节点的复制积压缓冲区中。过程从节点重新连接主节点发送PSYNC replid offset命令带上自己记录的复制 ID 和偏移量。主节点检查收到的复制 ID 是否与自己的当前复制 ID 匹配。请求的偏移量之后的数据是否还在自己的复制积压缓冲区中。如果条件满足主节点回复CONTINUE表示可以进行部分重同步。然后主节点将复制积压缓冲区中从请求偏移量开始的所有数据发送给从节点。从节点接收并执行这些命令从而将数据同步到最新状态。之后进入正常的命令传播阶段。如果条件不满足例如主节点复制 ID 变了或者请求偏移量之前的数据已被覆盖则主节点会回复FULLRESYNC replid offset触发一次全量同步。三、 主从复制的配置管理 (OpenEuler)在 OpenEuler 系统上配置 Redis 主从复制主要涉及修改 Redis 的配置文件redis.conf。以下列出关键配置项及其含义1. 主节点配置 (Master)主节点的配置通常相对简单主要是确保其可以接受连接并设置密码如果需要认证。关键配置项bind 0.0.0.0或bind specific_ip指定 Redis 监听的网络接口。0.0.0.0表示监听所有接口生产环境建议绑定具体 IP。port 6379监听端口默认 6379。requirepass password设置主节点的访问密码。强烈建议设置强密码。从节点连接时需要用到这个密码。masterauth password如果主节点自身也是另一个主节点的从节点级联复制则需要设置此项为它的主节点的密码。在纯主节点角色下此项不需要配置。maxmemory bytes设置最大内存限制根据服务器内存情况配置避免 OOM。repl-backlog-size size设置复制积压缓冲区大小。默认1mb。在断线重连频繁或网络不稳定的场景下建议增大此值例如128mb或256mb以减少全量同步的概率。值越大占用的内存越多。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 上通常使用systemctlsudo 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) - 从节点 1replica-node2(IP: 192.168.1.102) - 从节点 2步骤 1安装 Redis在所有三台服务器上安装 Redis。OpenEuler 通常可以通过dnf安装sudo dnf install redis -y安装完成后默认配置文件位于/etc/redis.conf。步骤 2配置主节点 (master-node)编辑/etc/redis.confsudo vim /etc/redis.conf找到并修改以下配置项# 绑定地址 (根据实际情况修改) 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保存并退出。创建日志和数据目录如果不存在sudo mkdir -p /var/log/redis /var/lib/redis sudo chown redis:redis /var/log/redis /var/lib/redis # 确保 Redis 用户有权限启动 Redis 服务sudo systemctl enable redis --now sudo systemctl status redis # 检查状态是否 active (running)步骤 3配置从节点 (replica-node1和replica-node2)分别在两台从节点服务器上编辑/etc/redis.confvim /etc/redis.conf修改以下配置项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保存并退出。创建目录并设置权限sudo mkdir -p /var/log/redis /var/lib/redis sudo chown redis:redis /var/log/redis /var/lib/redis启动 Redis 服务sudo systemctl enable redis --now sudo systemctl status redis步骤 4验证主从复制连接主节点在master-node或任何能访问主节点的机器上使用redis-cliredis-cli -h 192.168.1.100 -a your_strong_password执行命令INFO replication查看输出role:master确认角色。connected_slaves:2应该显示已连接的从节点数量。在slave0和slave1部分可以看到从节点的 IP、端口、状态 (online)、复制偏移量等信息。连接从节点连接其中一个从节点redis-cli -h 192.168.1.101 -a your_strong_password # 或用从节点自身密码执行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它们应该非常接近最终一致。测试数据同步在主节点上写入数据SET master_key Hello from Master在任意从节点上读取该数据GET master_key # 应返回 Hello from Master尝试在从节点上写入SET slave_key Try write # 应该会报错(error) READONLY You cant write against a read only replica.验证了从节点的只读属性。步骤 5模拟故障转移 (高级)主节点宕机手动停止主节点的 Redis 服务 (master-node)sudo systemctl stop redis观察从节点连接一个从节点执行INFO replicationmaster_link_status:down表示连接断开。客户端对从节点的读请求可能还能成功取决于数据是否最新但无法写入。手动切换主节点选择一个从节点如replica-node1提升为新的主节点连接到该从节点redis-cli -h 192.168.1.101 -a your_strong_password执行命令使其停止复制并成为主节点REPLICAOF NO ONE # 或 SLAVEOF NO ONE验证INFO replication # role 应变为 master重新配置其他从节点将另一个从节点 (replica-node2) 指向新的主节点 (192.168.1.101)连接到replica-node2redis-cli -h 192.168.1.102 -a your_strong_password执行REPLICAOF 192.168.1.101 6379验证INFO replication显示新的主节点信息且状态up。恢复原主节点如果原主节点恢复可以将其配置为当前新主节点 (192.168.1.101) 的从节点或者根据需要进行其他处理。注意上述步骤 5 是手动故障转移。在生产环境中通常使用Redis Sentinel或Redis Cluster来实现自动化的高可用和故障转移避免人工干预。五、 总结与注意事项Redis 主从复制是构建高可用 Redis 架构的基础。在 OpenEuler 系统上部署时需注意安全性务必为主节点和从节点设置强密码 (requirepass)并在从节点配置masterauth。避免使用protected-mode no暴露无密码实例到公网。配置优化根据网络和负载情况调整repl-backlog-size。谨慎使用无盘复制 (repl-diskless-sync)。监控定期使用INFO replication监控主从状态、偏移量差异和连接健康状况。只读从节点保持replica-read-only yes是标准做法除非有特殊需求。高可用主从复制本身不提供自动故障转移。对于生产环境强烈建议结合 Redis Sentinel 或 Redis Cluster来实现主节点故障时的自动切换保证服务连续性。持久化主从复制不是备份的替代品。仍然需要在主节点或从节点配置适当的 RDB 或 AOF 持久化策略防止数据丢失。网络确保主节点和从节点之间的网络通信畅通且延迟低以保证复制的实时性。