这篇是我把几套生产环境踩坑与复盘整理成的一份“从 0 到 1 + 长期可维护”的实践文。目标是:明确策略、给出默认可用的配置模板、把常见坑一次讲透。
适用场景:新项目选型、老项目稳定性加固、从单机迁移到 HA/Cluster、应对数据安全与故障切换要求。
目录
核心结论先说在前面
持久化:RDB vs AOF(以及“二者结合”的推荐范式)
高可用形态:主从复制基础、Sentinel、Cluster
典型拓扑与配置模板(可直接改名上线)
备份/恢复/演练:从脚本到流程
性能与稳定性调优(内核、Redis 配置、内存与淘汰)
生产避坑清单(高频问题→定位→对策)
迁移与升级策略(Standalone→Sentinel、Sentinel→Cluster)
运维清单与值班自检表
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 yes
、appendfsync everysec
、no-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 reshard
、add-node
、del-node
,务必在低峰期进行。
5. 备份/恢复/演练:从脚本到流程
5.1 备份策略
RDB 冷备:定期复制
.rdb
到异地/对象存储(带版本与校验);AOF:先
BGREWRITEAOF
生成紧凑版,再打包上传(避免巨大日志)。频率:日常建议 日备 + 周全量,重要业务增加关键时点手动快照。
校验:
redis-check-rdb dump-2025-09-01.rdb redis-check-aof appendonly.aof
5.2 恢复流程(单实例)
下线流量、停止 Redis;
备份当前数据文件到临时目录(防误操作);
放入目标
dump.rdb
(或appendonly.aof
),确保权限与 owner 一致;启动 Redis,观察日志与
INFO
;业务侧灰度放量。
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-lru
或allkeys-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. 生产避坑清单(高频问题→定位→对策)
BGSAVE/BGREWRITEAOF 失败
现象:日志提示
fork
失败或 OOM;排查:
vm.overcommit_memory
、内存碎片、容器内存限制;对策:开启
activedefrag
、扩内存、调整触发频率。
主从复制频繁全量
现象:网络抖动后总是从头同步;
排查:
repl-backlog-size
太小;对策:增大到能覆盖网络波动期的写入量(按 QPS 与命令平均大小估)。
写入被拒(OOM 或不安全写)
现象:
OOM command not allowed
/ 触发min-replicas-to-write
保护;对策:设置
maxmemory
与合理淘汰策略,或检查从库延迟/下线。
AOF 膨胀/恢复慢
现象:AOF 文件超大,重放耗时长;
对策:定期
BGREWRITEAOF
,启用“RDB 作为 AOF 前导”,老版本升级。
Cluster 跨槽操作失败
现象:
CROSSSLOT Keys in request don't hash to the same slot
;对策:使用 hash tag(如
user:{42}:profile
、order:{42}:list
)让相关 Key 落同槽。
Sentinel 频繁误判
现象:网络抖动导致频繁 failover;
对策:增大
down-after-milliseconds
、合理quorum
、跨 AZ 部署 Sentinel。
容器/云环境 IP 上报错误
现象:Cluster 节点互相连不上;
对策:显式设置
cluster-announce-ip
、cluster-announce-port
、protected-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 info
、cluster 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 和口令就能落地。