Redis 主从复制详解

📅 创建时间:2026-02-25
🏷️ 标签:#redis #主从复制 #高可用

一、什么是 Redis 主从复制

Redis 主从复制(Master-Slave Replication)是指将一台 Redis 服务器(主节点 Master)的数据,同步到其他一台或多台 Redis 服务器(从节点 Slave)的机制。

Pasted image 20260225161401

二、核心特点

1. 数据流向

  • 单向同步:只能从 Master 同步到 Slave,不能反向
  • 级联复制:Slave 也可以有自己的 Slave,形成级联结构

2. 读写分离

  • Master:负责写操作(也可读)
  • Slave:只负责读操作,不能写

3. 数据一致性

  • 最终一致性:Slave 数据会延迟于 Master
  • 异步复制:Master 不需等待 Slave 完成同步

三、主要作用与优势

✅ 1. 数据冗余备份

  • 提供数据的热备份,提高数据安全性
  • 当 Master 故障时,有完整的数据副本

✅ 2. 读写分离,性能提升

  • Master 负责写操作,分担写压力
  • 多个 Slave 负责读操作,提升读并发能力
  • 适合读多写少的业务场景

✅ 3. 高可用基础

  • 是 Redis Sentinel(哨兵)和 Redis Cluster(集群)的基础
  • 故障恢复:可以快速将从节点提升为主节点

✅ 4. 负载均衡

  • 多个从节点分担读请求
  • 可根据业务需求配置不同地理位置的从节点

四、工作原理

复制流程(全量复制 + 增量复制)

Pasted image 20260225142436|700

详细步骤:

1. 连接建立阶段

  • Slave 启动后,连接到 Master
  • 发送 PSYNC 命令请求同步

2. 全量同步阶段(初次)

  • Master 执行 BGSAVE 生成 RDB 快照
  • Master 将 RDB 文件发送给 Slave
  • Slave 接收并加载 RDB 文件
  • Master 将期间的写命令缓存并发送

3. 增量同步阶段(正常运行)

  • Master 每执行一个写命令,就发送给所有 Slave
  • Slave 执行接收到的命令,保持数据一致

4. 心跳检测

  • Slave 定期发送 REPLCONF ACK 报告复制进度
  • 检测网络连接状态

复制偏移量(Replication Offset)

  • Master 和 Slave 都维护一个复制偏移量
  • 表示当前复制的数据位置
  • 用于判断数据同步的状态和进度
Master: offset = 1000
          │ 写入了 10 字节数据
          ▼
Master: offset = 1010  ── 发送命令 ──>  Slave: offset = 1010

五、配置方法

1. 临时配置(命令行)

在 Slave 节点上执行:

# 连接到 Redis Slave
redis-cli -h slave_host -p 6379

# 设置主节点信息
SLAVEOF master_host master_port

# 如果 Master 设置了密码
CONFIG SET masterauth <password>

# 查看复制状态
INFO replication

2. 永久配置(配置文件)

在 Slave 的 redis.conf 文件中添加:

# 指定 Master 的 IP 和端口
slaveof master_host master_port

# 如果 Master 设置了密码
masterauth <master-password>

# 从节点只读(默认开启)
slave-read-only yes

# 从节点优先级(越小越优先被提升为主节点)
slave-priority 100

# 最小从节点连接数(新特性,用于保障数据安全)
min-slaves-to-write 1
min-slaves-max-lag 10

3. Docker 配置示例

# docker-compose.yml
version: '3'
services:
  redis-master:
    image: redis:7.0
    container_name: redis-master
    ports:
      - "6379:6379"
    command: redis-server --requirepass master123

  redis-slave1:
    image: redis:7.0
    container_name: redis-slave1
    ports:
      - "6380:6379"
    command: redis-server --slaveof redis-master 6379 --masterauth master123 --requirepass slave123
    depends_on:
      - redis-master

  redis-slave2:
    image: redis:7.0
    container_name: redis-slave2
    ports:
      - "6381:6379"
    command: redis-server --slaveof redis-master 6379 --masterauth master123 --requirepass slave123
    depends_on:
      - redis-master

六、关键配置参数详解

主节点相关参数

# 设置密码(同时影响主从复制)
requirepass <password>

# 允许写入的最少从节点数(保障数据安全)
min-slaves-to-write 1

# 从节点最大延迟(秒)
min-slaves-max-lag 10

从节点相关参数

# 指定主节点
slaveof <masterip> <masterport>

# 主节点密码
masterauth <master-password>

# 从节点只读
slave-read-only yes

# 从节点优先级(越小越优先)
slave-priority 100

# 从节点断开连接后是否继续服务旧数据
slave-serve-stale-data yes

# 从节点是否开启 TCP_NODELAY(减少延迟)
repl-disable-tcp-nodelay no

网络相关参数

# 复制积压缓冲区大小(用于增量同步)
repl-backlog-size 1mb

# 复制积压缓冲区保留时间
repl-backlog-ttl 3600

# 主从节点心跳间隔(秒)
repl-ping-slave-period 10

# 从节点超时时间(秒)
repl-timeout 60

七、监控与管理

1. 查看复制状态

# 在 Master 上执行
127.0.0.1:6379> INFO replication
# Output:
# role:master
# connected_slaves:2
# slave0:ip=192.168.1.101,port=6379,state=online,offset=12345,lag=0
# slave1:ip=192.168.1.102,port=6379,state=online,offset=12345,lag=0

# 在 Slave 上执行
127.0.0.1:6379> INFO replication
# Output:
# role:slave
# master_host:192.168.1.100
# master_port:6379
# master_link_status:up
# master_last_io_seconds_ago:3
# master_sync_in_progress:0
# slave_repl_offset:12345

2. 关键监控指标

指标 说明 健康值
master_link_status 主从连接状态 up
master_last_io_seconds_ago 最后一次通信时间 < 10秒
slave_repl_offset 复制偏移量 与 Master 接近
master_sync_in_progress 是否正在同步 0(空闲)
connected_slaves Master 连接的从节点数 >= 2(生产环境)

3. 监控脚本示例

#!/bin/bash
# monitor_redis_replication.sh

MASTER_HOST="192.168.1.100"
MASTER_PORT="6379"

echo "=== Redis Replication Status ==="
echo "Time: $(date)"

# 检查 Master
MASTER_INFO=$(redis-cli -h $MASTER_HOST -p $MASTER_PORT INFO replication)
SLAVE_COUNT=$(echo "$MASTER_INFO" | grep "connected_slaves" | cut -d: -f2)

echo "Master: $MASTER_HOST:$MASTER_PORT"
echo "Connected Slaves: $SLAVE_COUNT"

# 检查每个 Slave
echo "$MASTER_INFO" | grep "slave" | while read line; do
    IP=$(echo $line | cut -d: -f2 | cut -d, -f1 | cut -d= -f2)
    PORT=$(echo $line | cut -d: -f2 | cut -d, -f2 | cut -d= -f2)
    STATE=$(echo $line | cut -d: -f2 | cut -d, -f3 | cut -d= -f2)
    LAG=$(echo $line | cut -d: -f2 | cut -d, -f5 | cut -d= -f2)

    echo "  - Slave: $IP:$PORT, State: $STATE, Lag: ${LAG}s"

    if [ "$STATE" != "online" ]; then
        echo "    ⚠️  WARNING: Slave is not online!"
    fi

    if [ "$LAG" -gt 10 ]; then
        echo "    ⚠️  WARNING: Replication lag is too high!"
    fi
done

echo "================================"

八、常见问题与故障处理

❌ 问题 1:从节点无法连接主节点

现象master_link_status: down

排查步骤

  1. 检查网络连通性:ping master_host
  2. 检查端口是否开放:telnet master_host master_port
  3. 检查 Master 密码是否正确:masterauth 配置
  4. 检查防火墙设置
  5. 查看 Redis 日志:tail -f /var/log/redis/redis-server.log

解决方案

# 重新配置主节点
redis-cli SLAVEOF NO ONE  # 先断开
redis-cli SLAVEOF master_host master_port  # 再重新连接

❌ 问题 2:复制延迟过高

现象master_last_io_seconds_ago > 30秒 或 lag 值很大

原因

  • 网络带宽不足
  • Master 写入量过大
  • Slave 性能不足(CPU/内存)
  • 存在慢查询阻塞

解决方案

  1. 优化网络环境
  2. 增加 Slave 节点分担读压力
  3. 升级 Slave 硬件配置
  4. 优化 Redis 配置:repl-disable-tcp-nodelay no
  5. 监控慢查询:SLOWLOG GET 10

❌ 问题 3:全量同步频繁

现象:日志中频繁出现 Full resync

原因

  • 复制积压缓冲区 repl-backlog-size 太小
  • 网络不稳定导致连接断开
  • Slave 重启或网络中断时间过长

解决方案

# 增加复制积压缓冲区
repl-backlog-size 256mb

# 增加缓冲区保留时间
repl-backlog-ttl 7200

❌ 问题 4:复制中断后无法恢复

现象:Slave 断开连接后无法自动重连

原因

  • Master 的 maxmemory 配置导致写操作失败
  • 客户端输出缓冲区溢出

解决方案

# 增加客户端输出缓冲区限制
client-output-buffer-limit slave 256mb 64mb 60

# 确保 Master 有足够的内存
maxmemory-policy allkeys-lru  # 或其他合适的淘汰策略

九、架构注意事项

📌 1. 数据一致性

  • 异步复制:Master 不等待 Slave 确认,存在数据丢失风险
  • 复制延迟:Slave 数据可能落后于 Master
  • 解决方案
    • 对强一致性要求高的业务,读 Master
    • 使用 WAIT 命令等待至少 N 个 Slave 同步

📌 2. 故障恢复

# Slave 提升为 Master
docker exec -it redis-slave1 redis-cli
> SLAVEOF NO ONE
> CONFIG SET slave-read-only no

# 将其他 Slave 指向新的 Master
docker exec -it redis-slave2 redis-cli
> SLAVEOF new_master_ip new_master_port

📌 3. 读写分离实现

在应用层实现读写分离:
// Java 示例 - Spring Boot
@Configuration
public class RedisConfig {

    @Bean
    public LettuceConnectionFactory masterConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("master_host", 6379);
        return new LettuceConnectionFactory(config);
    }

    @Bean
    public LettuceConnectionFactory slaveConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("slave_host", 6379);
        return new LettuceConnectionFactory(config);
    }

    @Bean(name = "masterRedisTemplate")
    public RedisTemplate<String, Object> masterRedisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(masterConnectionFactory());
        return template;
    }

    @Bean(name = "slaveRedisTemplate")
    public RedisTemplate<String, Object> slaveRedisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(slaveConnectionFactory());
        return template;
    }
}

@Service
public class UserService {

    @Autowired
    @Qualifier("masterRedisTemplate")
    private RedisTemplate<String, Object> masterRedisTemplate;

    @Autowired
    @Qualifier("slaveRedisTemplate")
    private RedisTemplate<String, Object> slaveRedisTemplate;

    public void saveUser(User user) {
        // 写操作:使用 Master
        masterRedisTemplate.opsForValue().set("user:" + user.getId(), user);
    }

    public User getUser(Long id) {
        // 读操作:使用 Slave
        return (User) slaveRedisTemplate.opsForValue().get("user:" + id);
    }
}

📌 4. 生产环境建议

架构图

          ┌─────────────┐
          │  Load Balancer
          │  (读请求分发)
          └──────┬──────┘
                 │
        ┌────────┼────────┬────────┐
        ▼        ▼        ▼        ▼
    ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
    │ Slave 1 │ │ Slave 2 │ │ Slave 3 │ │ Slave N │
    │  (读)   │ │  (读)   │ │  (读)   │ │  (读)   │
    └─────────┘ └─────────┘ └─────────┘ └─────────┘
                         │
                         │ 写入/复制
                         ▼
                  ┌─────────────┐
                  │ Redis Master│
                  │   (写)      │
                  └─────────────┘

最佳实践

  1. 至少 2 个从节点:保证高可用性
  2. 异地备份:将 Slave 部署在不同机房
  3. 监控延迟:设置告警阈值(如 lag > 10s)
  4. 网络质量:确保主从之间网络稳定、低延迟
  5. 容量规划:Slave 配置不低于 Master
  6. 密码认证:生产环境必须设置强密码

📌 5. 升级与维护

# 平滑升级 Slave 步骤:
1. 停止 Slave 服务
2. 备份数据
3. 升级 Redis 版本
4. 启动 Slave 服务
5. 验证复制状态
6. 重复 1-5 对其他 Slave
7. 手动故障转移(Master -> Slave)
8. 升级原 Master

# 使用 Sentinel 自动故障转移(推荐)

十、总结

主从复制适用场景

适合

  • 读多写少的业务场景
  • 数据备份和容灾恢复
  • 读写分离提升性能
  • 构建 Redis 高可用架构

不适合

  • 频繁网络波动的环境
  • 需要强一致性的场景
  • 写入量远大于读取量的场景

关键配置回顾

配置项 作用 推荐值
slaveof 指定主节点 IP:PORT
masterauth 主节点密码 强密码
slave-read-only 从节点只读 yes
repl-backlog-size 复制积压缓冲区 256MB+
repl-timeout 复制超时时间 60-120s
slave-priority 从节点优先级 100

下一步学习建议

  • 阅读 [[Redis Sentinel 哨兵机制详解]] → 实现自动故障转移
  • 阅读 [[Redis Cluster 集群详解]] → 实现数据分片和水平扩展
  • 实践:在本地搭建一主二从架构并测试故障转移

参考资料

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐