Redis 持久化与高可用实践(RDB / AOF / Sentinel / Cluster 全解析)

这篇是我把几套生产环境踩坑与复盘整理成的一份"从 0 到 1 + 长期可维护"的实践文。目标是:明确策略、给出默认可用的配置模板、把常见坑一次讲透

适用场景:新项目选型、老项目稳定性加固、从单机迁移到 HA/Cluster、应对数据安全与故障切换要求。


目录

  1. 核心结论先说在前面

  2. 持久化:RDB vs AOF(以及"二者结合"的推荐范式)

  3. 高可用形态:主从复制基础、Sentinel、Cluster

  4. 典型拓扑与配置模板(可直接改名上线)

  5. 备份/恢复/演练:从脚本到流程

  6. 性能与稳定性调优(内核、Redis 配置、内存与淘汰)

  7. 生产避坑清单(高频问题→定位→对策)

  8. 迁移与升级策略(Standalone→Sentinel、Sentinel→Cluster)

  9. 运维清单与值班自检表


1. 核心结论先说在前面

  • 持久化策略

    • 低延迟场景:首选 RDB + AOF(everysec) 组合。RDB 提供"冷备点",AOF 控制丢失窗口(通常 ≤1s)。

    • 极端数据安全:AOF(appendfsync always),但写放大大、吞吐下降明显,一般不建议全站开启。

    • 只读/可丢缓存:可以 仅 RDB 或甚至关闭持久化,靠上游重建(但要清楚发生重启的业务影响)。

  • 高可用形态

    • 单实例 HA:主从 + Sentinel(入门首选,维护简单,客户端/驱动支持成熟)。

    • 水平扩展 + HA:Redis Cluster(3 主 3 备起步) 。选它是因为容量/吞吐/隔离/自治 ,也要接受跨槽限制

  • 复制一致性 :Redis 复制本质是异步。务必配合:

    • min-replicas-to-write / min-replicas-max-lag(提升写安全,避免主孤岛)

    • 按需使用 WAIT 命令等待复制到 N 个副本再返回(强一致片段,但影响时延)。

  • 默认稳妥配置(可作为起步模板):

    • appendonly yesappendfsync everysecno-appendfsync-on-rewrite yes

    • save 900 1 / save 300 10 / save 60 10000(按业务写入频率调整)

    • stop-writes-on-bgsave-error yes(防止静默数据丢失)

    • repl-backlog-size 256mb(按主写入速率与断链窗口估算)

    • maxmemory + 合理淘汰策略(缓存型业务尤为重要)


2. 持久化:RDB vs AOF(以及"二者结合"的推荐范式)

2.1 RDB(快照)

  • 原理 :定期把内存快照写入 .rdb 文件(BGSAVE 子进程)。

  • 优点:文件小、恢复快、对线上写入影响较小(写时复制)。

  • 缺点 :两次快照之间的新写入可能丢失

  • 关键配置

    复制代码
    # 触发条件按需调整(示例:90% 读多写少)
    save 900 1
    save 300 10
    save 60 10000
    
    rdbcompression yes
    rdbchecksum yes
    stop-writes-on-bgsave-error yes

2.2 AOF(追加日志)

  • 原理 :把写命令追加到日志;重启时"重放"恢复。Redis 新版本使用 多段 AOF(BASE/INCR),并支持 RDB 作为 AOF 前导以加速恢复。

  • 优点更小的数据丢失窗口everysec 常见);可以手工编辑修复尾部。

  • 缺点:文件膨胀、重写时可能有额外 I/O 压力。

  • 关键配置

    复制代码
    appendonly yes
    appendfsync everysec           # 安全与性能折中(常用)
    no-appendfsync-on-rewrite yes  # 重写期间尽量少阻塞
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    aof-load-truncated yes
    # 新版:AOF 使用 RDB 作为 preamble(通常默认开启,恢复更快)
    # aof-use-rdb-preamble yes

2.3 推荐组合:RDB + AOF(everysec)

  • 为什么:RDB 提供"恢复基线",AOF 提供"小丢失窗口";重启时优先加载 AOF,若 AOF 不可用仍可回退到 RDB。

  • 通用建议先做对的,再做快的。先把 AOF + 定期 RDB 固住,再谈参数与 I/O 优化。


3. 高可用形态:主从复制基础、Sentinel、Cluster

3.1 主从复制基础

  • 复制机制 :初次全量同步 + 之后命令流增量;断联后支持部分重同步(PSYNC)

  • 常用参数

    复制代码
    replica-read-only yes
    repl-diskless-sync yes
    repl-diskless-sync-delay 5
    repl-backlog-size 256mb
    min-replicas-to-write 1         # 至少有1个副本在线主才写
    min-replicas-max-lag 5          # 超过5s延迟则视为不安全
  • 只读从库:默认只读,适合做报表与只读流量分流(避免主库压力过大)。

3.2 Sentinel(哨兵)

  • 作用 :自动故障检测、投票选主、通知客户端新主地址

  • 部署 :至少 3 个哨兵实例 (奇数),建议与 Redis 节点分机房/可用区部署。

  • 核心配置sentinel.conf):

    复制代码
    port 26379
    daemonize yes
    
    # 监控一个 master:<name> <ip> <port> <quorum>
    sentinel monitor app-master 10.0.0.10 6379 2
    
    sentinel down-after-milliseconds app-master 5000
    sentinel failover-timeout app-master 60000
    sentinel parallel-syncs app-master 1
    
    # 可选:通知/脚本
    # sentinel notification-script app-master /opt/sentinel/notify.sh
    # sentinel client-reconfig-script app-master /opt/sentinel/reconfig.sh
  • 客户端接入

    • 方式一:连接哨兵,按 master name 查询主;

    • 方式二:用支持 Sentinel 的驱动(Java/Lettuce、Go/redis、Node/ioredis 等)自动刷新连接。

3.3 Redis Cluster(分片+高可用)

  • 特性:16384 槽位(hash slot)分布到多主节点,每个主有 ≥1 个副本;主节点故障时由副本升主。

  • 限制 :多键操作需在同槽 (可用 {tag} 控制);Lua 脚本/事务等有跨槽限制。

  • 常用参数redis.conf):

    复制代码
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 15000
    cluster-announce-ip 10.0.0.10     # 跨网段/容器时要显式设置
    cluster-announce-port 6379
    cluster-announce-bus-port 16379
  • 集群建议规模3 主 3 备起步(6 节点),单 AZ 内至少 3 台物理/虚拟机,尽量跨 AZ。

  • 创建与检查

    复制代码
    # 创建集群(示例6节点,3主3从)
    redis-cli --cluster create \
      10.0.0.10:6379 10.0.0.11:6379 10.0.0.12:6379 \
      10.0.0.13:6379 10.0.0.14:6379 10.0.0.15:6379 \
      --cluster-replicas 1
    
    # 查看拓扑
    redis-cli -c -h 10.0.0.10 -p 6379 cluster nodes
    redis-cli -c -h 10.0.0.10 -p 6379 cluster info

4. 典型拓扑与配置模板(可直接改名上线)

4.1 单实例高可用(主从 + Sentinel)

  • 拓扑1 主 + 2 从 + 3 Sentinel

  • 适用:中小体量、强一致要求不高、运维成本友好。

  • 主库片段(redis.conf)

    复制代码
    port 6379
    # 持久化
    save 900 1
    save 300 10
    save 60 10000
    appendonly yes
    appendfsync everysec
    no-appendfsync-on-rewrite yes
    
    # 复制与安全
    repl-diskless-sync yes
    repl-backlog-size 256mb
    min-replicas-to-write 1
    min-replicas-max-lag 5
    
    # 内存
    maxmemory 16gb
    maxmemory-policy allkeys-lru
    
    # 安全(按需)
    # requirepass <pass>
    # aclfile /etc/redis/users.acl
  • 从库片段

    复制代码
    replicaof 10.0.0.10 6379
    replica-read-only yes
  • Sentinel(3 份,仅示例一份):见上 3.2 配置。

4.2 Redis Cluster(3 主 3 从)

  • 每个节点的 redis.conf (变化项:cluster-announce-ip、端口):

    复制代码
    port 6379
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 15000
    
    # 持久化
    appendonly yes
    appendfsync everysec
    save 900 1
    save 300 10
    
    # 内存淘汰(缓存型很关键)
    maxmemory 16gb
    maxmemory-policy allkeys-lru
  • 创建集群:参考 3.3 脚本。

  • 扩容/缩容 :使用 redis-cli --cluster reshardadd-nodedel-node,务必在低峰期进行。


5. 备份/恢复/演练:从脚本到流程

5.1 备份策略

  • RDB 冷备 :定期复制 .rdb 到异地/对象存储(带版本与校验);

  • AOF :先 BGREWRITEAOF 生成紧凑版,再打包上传(避免巨大日志)。

  • 频率 :日常建议 日备 + 周全量,重要业务增加关键时点手动快照。

  • 校验

    复制代码
    redis-check-rdb dump-2025-09-01.rdb
    redis-check-aof appendonly.aof

5.2 恢复流程(单实例)

  1. 下线流量、停止 Redis;

  2. 备份当前数据文件到临时目录(防误操作);

  3. 放入目标 dump.rdb(或 appendonly.aof),确保权限与 owner 一致;

  4. 启动 Redis,观察日志与 INFO

  5. 业务侧灰度放量。

5.3 恢复流程(Cluster)

  • 同槽迁移:尽量在集群内重建节点而非整体"外部恢复";

  • 节点级恢复 :按节点维度恢复 RDB/AOF,重入集群(CLUSTER MEET),再做 slot 迁移;

  • 强演练:每季度做一次"节点级数据损坏恢复演练",记录耗时与回放步骤。


6. 性能与稳定性调优(内核、Redis 配置、内存与淘汰)

6.1 系统内核与文件系统

复制代码
# 软中断/网络 backlog
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=8192

# TIME_WAIT 回收(按需,谨慎)
sysctl -w net.ipv4.tcp_tw_reuse=1

# 关闭透明大页(THP)
echo never > /sys/kernel/mm/transparent_hugepage/enabled

# 关闭 swap 或保证 swapiness 很低
sysctl -w vm.swappiness=1

# 允许内存 overcommit(防止 fork 失败)
sysctl -w vm.overcommit_memory=1

重点vm.overcommit_memory=1,否则 BGSAVE/BGREWRITEAOF 可能因内存不足失败。

6.2 Redis 配置热点

  • 延迟敏感

    • appendfsync everysec + no-appendfsync-on-rewrite yes

    • latency-monitor-threshold 100(打开延迟监控,单位毫秒)

  • 内存与碎片

    • maxmemory <size> + 合理 maxmemory-policy(缓存型推荐 allkeys-lruallkeys-lfu

    • activedefrag yes(生产常开,降低碎片)

  • 数据结构优化

    • 小对象压缩阈值(具体名称随版本有变化,如 listpack 相关阈值);

    • 尽量使用紧凑结构(如 Hash 存多字段,避免大量小 Key)。

6.3 慢查询与可观测性

复制代码
# 记录慢查询(单位微秒)
CONFIG SET slowlog-log-slower-than 10000   # >10ms
CONFIG SET slowlog-max-len 2048

# 查看慢日志
SLOWLOG GET 10

# 延迟事件
LATENCY DOCTOR
LATENCY LATEST
  • 打通 Exporter → Prometheus → Grafana,关注内存碎片率、AOF 重写耗时、复制延迟、拒绝写入次数等核心指标。

7. 生产避坑清单(高频问题→定位→对策)

  1. BGSAVE/BGREWRITEAOF 失败

    • 现象:日志提示 fork 失败或 OOM;

    • 排查:vm.overcommit_memory、内存碎片、容器内存限制;

    • 对策:开启 activedefrag、扩内存、调整触发频率。

  2. 主从复制频繁全量

    • 现象:网络抖动后总是从头同步;

    • 排查:repl-backlog-size 太小;

    • 对策:增大到能覆盖网络波动期的写入量(按 QPS 与命令平均大小估)。

  3. 写入被拒(OOM 或不安全写)

    • 现象:OOM command not allowed / 触发 min-replicas-to-write 保护;

    • 对策:设置 maxmemory 与合理淘汰策略,或检查从库延迟/下线。

  4. AOF 膨胀/恢复慢

    • 现象:AOF 文件超大,重放耗时长;

    • 对策:定期 BGREWRITEAOF,启用"RDB 作为 AOF 前导",老版本升级。

  5. Cluster 跨槽操作失败

    • 现象:CROSSSLOT Keys in request don't hash to the same slot

    • 对策:使用 hash tag (如 user:{42}:profileorder:{42}:list)让相关 Key 落同槽。

  6. Sentinel 频繁误判

    • 现象:网络抖动导致频繁 failover;

    • 对策:增大 down-after-milliseconds、合理 quorum、跨 AZ 部署 Sentinel。

  7. 容器/云环境 IP 上报错误

    • 现象:Cluster 节点互相连不上;

    • 对策:显式设置 cluster-announce-ipcluster-announce-portprotected-mode no(仅在安全网络下)。


8. 迁移与升级策略(Standalone→Sentinel、Sentinel→Cluster)

8.1 单机→Sentinel(无停机/短暂停)

  • 新建两个从库(全量同步完成后),部署 3 哨兵;

  • 切流量前压测读从(确认只读链路 OK);

  • 客户端切到 Sentinel 模式;

  • 小流量灰度 → 全量切换。

8.2 单机/Sentinel→Cluster(平滑迁移)

  • 新建 Cluster(3 主 3 从),业务新写双写(或通过数据管道/订阅复制);

  • 扫描旧库 Key,分批迁移到 Cluster(redis-shake/自研脚本/SCAN + MIGRATE);

  • 验证一致性(抽样校验、核心集合完整性校验);

  • 写流量切换到 Cluster → 读流量切换 → 观测一段时间 → 下线旧库。

若业务允许短暂停机,关闭写入口,做全量迁移 + 增量补偿,会简单很多。

8.3 版本升级

  • 同大版本小修:rolling 重启(从→主),使用 REPLICAOF 切换,缩短中断;

  • 跨大版本:先读 release notes 看持久化格式/配置项兼容性,影子集群演练,再灰度。


9. 运维清单与值班自检表

日常巡检(每日/每班次):

  • INFO replication:复制延迟、master_link_status

  • INFO persistence:AOF 重写状态、最近持久化失败次数;

  • INFO memory:使用量、碎片率(>1.5 长期需关注);

  • SLOWLOG LEN / SLOWLOG GET:慢查询堆积;

  • Cluster:cluster infocluster nodes 异常标记。

周度/关键变更前:

  • 触发 RDB 快照与 AOF 重写,校验备份;

  • Sentinel/Cluster 拓扑一致性检查;

  • 压测核心读写路径,记录基线。

季度演练:

  • 单节点宕机 → 恢复;

  • 主从切换演练(Sentinel/Cluster);

  • 备份恢复全链路复盘(计时 + 步骤卡点)。


附:一键化示例(可改名投入使用)

systemd 单实例服务(/etc/systemd/system/redis-6379.service

复制代码
[Unit]
Description=Redis 6379
After=network.target

[Service]
ExecStart=/usr/bin/redis-server /etc/redis/6379.conf --supervised systemd
ExecStop=/usr/bin/redis-cli -p 6379 shutdown
Type=notify
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target

Sentinel systemd(/etc/systemd/system/redis-sentinel.service

复制代码
[Unit]
Description=Redis Sentinel
After=network.target

[Service]
ExecStart=/usr/bin/redis-sentinel /etc/redis/sentinel.conf --supervised systemd
ExecStop=/usr/bin/redis-cli -p 26379 shutdown
Type=notify
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target

结语

Redis 的"正确打开方式"不是单点性能跑多快,而是在"可预期的失败"里依然稳定工作

  • RDB + AOF(everysec) 做好数据兜底;

  • 主从 + Sentinel 扛住单点;

  • 需要水平扩展就上 Cluster ,在建模时用 {} 控制跨槽;

  • 结合 操作系统与 Redis 参数 做到"高性能但不冒险";

  • 备份/恢复/演练 变成固定流程,而不是事故现场临时发挥。

如果你愿意,我可以把上述模板整理成 可下载的配置包 (包含 redis.conf/sentinel.conf/systemd/备份脚本/演练脚本),你直接改 IP 和口令就能落地。

相关推荐
mask哥2 小时前
详解mcp以及agen架构设计与实现
java·微服务·flink·大模型·ai agent·springai·mcp
Propeller2 小时前
【Android】View 交互的事件处理机制
android·java
杨杨杨大侠2 小时前
Atlas Mapper 教程系列 (5/10):集合映射与嵌套对象处理
java·开源·github
ERP老兵_冷溪虎山2 小时前
Python/JS/Go/Java同步学习(第十三篇)四语言“字符串转码解码“对照表: 财务“小南“纸式转码术处理凭证乱码崩溃(附源码/截图/参数表/避坑指南)
java·后端·python
是2的10次方啊2 小时前
如何设计10万QPS秒杀系统?缓存+消息队列+分布式锁架构实战
java
心灵宝贝2 小时前
Tomcat Connectors 1.2.37 源码编译安装教程(mod_jk 详细步骤)
java·tomcat
杨杨杨大侠2 小时前
Atlas Mapper 教程系列 (6/10):Spring Boot 集成与自动配置
java·开源·github
傻傻虎虎3 小时前
【Docker】容器端口暴露+镜像生成实战
java·docker·容器
练习时长一年3 小时前
搭建langchain4j+SpringBoot的Ai项目
java·spring boot·后端