尼恩说在前面
在45岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:
- Redis挂了怎么办?
- 追问: Redis Cluster 挂一个主节点,是怎么 恢复数据?
- 追问:redis Cluster 主从切换, 可能出现多长时间的数据丢失?
- 追问:Redis cluster 集群里边的 节点,怎么配置持久化?
最近有小伙伴在面试京东、 阿里、希音等大厂,又遇到了相关的面试题。 小伙伴 没系统梳理, 支支吾吾的说了几句, 面试官不满意,卒。尼恩提示:redis 是多么核心的组件,是多么重要的组件。连 Redis挂了, 竟然不知道怎么处理,怎么可能是技术高手呢?怎么可能 通过面试呢?接下来 45岁老架构师 尼恩给 大家做一下系统化、体系化的梳理。 使得大家内力猛增。帮助大家 充分展示一下 雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”+”offer自由”。这道 题 以及参考答案, 会收入咱们的 《尼恩Java面试宝典PDF》V175版本,供后面的小伙伴参考 ,帮助大家进大厂/做架构。
最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书
一、面试暴击:Redis挂了怎么办?
Redis作为高性能的内存数据库,在企业应用中扮演着至关重要的角色。然而,由于其数据主要存储在内存中,一旦服务器发生故障或重启,所有数据将面临丢失风险。下面来深入探讨Redis持久化机制,帮助您了解如何在Redis服务中断时最大限度地保障数据安全,并实现快速恢复。Redis 虽然提供了极高的读写性能,但宕机也带来了 性能的严重挑战。当服务器意外宕机或重启时,内存中的数据将全部丢失,这对于业务系统来说可能是灾难性的。
快速止血 流程
Redis 节点挂,会让人 极度 紧张,需要 一套清晰的应急流程, 帮助应急处理,快速恢复。其处理核心遵循一个清晰的 快速止血 流程: 快速诊断 → 紧急恢复服务 → 数据恢复与根因修复 → 长期优化预防。
第一步:快速诊断与应急恢复
当收到报警或发现应用报错(如 Connection refused
)时,首要目标是确认状态并尽快恢复基本服务。1、检查Redis服务状态:登录服务器,查看Redis进程是否在运行。执行 ps aux | grep redis
命令或 执行 systemctl status redis
命令2、查看日志定位原因:如果服务异常,立即查看Redis日志.Redis日志 通常位于 /var/log/redis/redis-server.log
。重点关注:
- 内存不足(Out of memory)
- 持久化失败(Background save failed)
- 慢查询(Timeout)
等错误信息,这能直接指引排查方向。3、尝试重启服务:如果是简单的进程卡死或配置更新,重启往往是最快的方法。使用命令
systemctl restart redis
- 或
redis-server /path/to/redis.conf
命令。
4、启用应用层降级方案:如果Redis无法立即重启恢复,为了不影响核心业务,应立即启动降级策略。包括 读请求降级、或者写请求降级:
- 读请求:直接访问后端数据库(如MySQL)。
- 写请求:先写入数据库,并记录日志或发送消息到消息队列,待Redis恢复后异步同步数据。
在Java应用中,降级方案 通常通过配置中心动态开关缓存功能,或使用Hystrix、Sentinel等组件实现自动熔断和降级
第二步:数据恢复
服务进程恢复后,下一步是确保数据完整性。 具体方法取决于您配置的持久化方式。
持久化方式 | 恢复原理 | 操作要点 |
AOF(追加日志) | Redis重启后重新执行AOF文件中的所有写命令来重建数据状态,数据完整性高。 | 确保 appendonly yes 配置已开启,AOF文件路径正确。 |
RDB(快照) | Redis启动时自动加载指定的RDB快照文件(如 dump.rdb )到内存中。 |
将最新的RDB文件放在配置的 dir 目录下。恢复速度快,但可能丢失最后一次快照后的数据。 |
从备份恢复 | 如果持久化文件损坏或丢失,需从备份恢复。 | 停止Redis服务 → 用最近的备份文件替换当前数据目录下的文件 → 重启Redis。定期备份至关重要。 |
第三步:根因分析与长期优化(事后复盘)
故障解决后,最重要的工作是复盘,防止同类问题再次发生。根因一:集群化部署架构,搭建高可用集群绝对不要在生产环境使用单机Redis。这是最核心的教训。请根据业务场景选择:
- Redis Sentinel(哨兵):提供自动故障转移,适合需要高可用但数据量不大的场景。
- Redis Cluster(集群):提供数据分片(Sharding)和高可用,适合大数据量和超高并发场景。
根因二:配置与监控层面
- 资源限制:在
redis.conf
中设置maxmemory
并配置合理的maxmemory-policy
(内存淘汰策略),防止内存耗尽。 - 全面监控:使用 Prometheus + Grafana 等工具监控内存使用率、连接数、延迟等关键指标,并设置告警。
- 处理大Key/热Key:定期使用
redis-cli --bigkeys
分析,并拆分大Key,避免单点瓶颈。
总结:故障处理核心原则
面对Redis故障,请牢记三个关键原则:1、快速止血:先通过重启或降级保障服务可用性,再彻底解决问题 。2、数据为王:依据持久化配置恢复数据,并始终保有可靠的备份 。3、防患未然:通过高可用架构、合理配置和严密监控,从根本上提升系统韧性 。
接下来,对面试官来一次 高维暴击:
到了这里,面试官开始 满意了。不过, 尼恩提示, 这个时候,可以进一步告诉面试官,咱们线上早期使用单体redis,后面 升级到 集群redis 啦。集群redis 是自动恢复的。单个节点挂了,不用那么手忙脚乱的了。
面试官追问:Redis Cluster 挂一个主节点,是怎么 恢复数据?
还有: 主节点变成从节点后,是从 日志文件恢复数据,还是从 新的主节点恢复数据?
总体的思路是:在 Redis Cluster 中,当主节点故障, 从节点会自动 投票 晋升, 成为 new master 。如果原主节点重启,首先会从日志文件恢复数据。原主节点 重启 后,原主节点 降级为 从节点 new slave。接下来, new slave 从 new master 的复制同步 最新增量数据 。
1、故障切换时的数据一致性基础
故障前, 所有slave 会通过主从复制, 实时同步old master 主节点的数据(通过replicaof
机制)。当 old master 主节点宕机时,slave 们 已保存了主节点故障前的大部分数据 。故障转移后,通过投票,一个slave 从节点 变成 new master 新主节点, 本身就持有接近完整的数据(这里是接近),切换过程中可能出现数据丢失, 这个丢失的时间很短,几百毫秒~几秒。
2、原主节点恢复后的角色与数据同步流程
原主节点修复重启后,会经历以下过程:1、自身初始化:加载持久化文件(日志的作用)原主节点重启时,会先加载自身的持久化文件(RDB 或 AOF,取决于配置),恢复到宕机前的状态。这一步依赖自身的日志文件,但仅能恢复到它宕机时的数据,无法获取它宕机期间新主节点接收的新数据。2、角色转换:成为新主节点的从节点重启后的原主节点会联系哨兵集群,哨兵会检测到它已上线,并自动向它发送replicaof 新主节点IP:端口
命令,将其设置为新主节点的从节点。3、数据同步:从新主节点复制增量数据此时,原主节点(已成为从节点)会向新主节点发起复制请求,具体分为两种情况:
- 若原主节点的复制偏移量(宕机前记录的同步位置)与新主节点的偏移量差距较小,新主节点会发送增量数据(通过 PSYNC 命令,基于偏移量同步缺失的部分)。
- 若差距过大(如新主节点已清理了部分复制积压缓冲区),新主节点会触发全量同步:发送自身的 RDB 文件给新从节点(原主节点),新从节点加载 RDB 后,再同步后续的增量数据。
最终,新从节点(原主节点) 会与新主节点(原从)的数据完全一致,包括它宕机期间新主节点接收的所有数据。
3、 数据恢复的两个来源
- 来源之一:存量恢复。 原主节点的日志文件(RDB/AOF)
将用于重启时恢复自身宕机前的数据,无法补充它离线期间集群新增的数据。
- 来源之二:增量同步。从新主节点的复制同步
真正让它与集群保持一致的是从新主节点的复制同步,这是 Redis Cluster 保证数据一致性的核心机制。这种设计的原因是:原主节点宕机, 新主节点在原主宕机后已承接了写请求,持有最新的数据,原主作为从节点必须以新主的数据为准,才能避免集群数据冲突。
面试官追问:redis Cluster 主从切换, 可能出现多长时间的数据丢失?
Redis 主从切换过程中,数据丢失的时间窗口, 取决于主从同步延迟和切换触发方式。核心结论:几百毫秒 ~ 数秒
1、正常情况(异步复制)
丢失时间:几百毫秒~几秒原因:主节点异步同步数据到从节点,切换瞬间, 未同步的数据会丢失。举例:如果主从延迟为 500ms,那么最多可能丢失最近 500ms 内的写操作。
2、极端情况(配置不当或延迟大)
丢失时间:数秒~分钟级原因:
- 从节点存在大延迟(如网络拥堵、从节点性能差)。
- 主节点突然宕机,未来得及同步任何数据。
- 新主节点配置错误(如
maxmemory
设置过小),导致切换后大量 key 被驱逐,表现为“数据丢失”。
3 如何估算最大可能丢失时间?
Redis 提供了两个关键配置参数,可限制最大数据丢失时间窗口:
配置项 | 含义 | 示例值 |
min-slaves-max-lag |
允许的最大主从同步延迟(秒) | 5 |
min-slaves-to-write |
主节点必须连接的从节点数 | 1 |
当所有从节点的同步延迟都超过 min-slaves-max-lag
秒时,主节点会拒绝写请求,从而将数据丢失时间控制在设定范围内。
- 设置
min-slaves-max-lag
和min-slaves-to-write
,强制控制数据丢失时间窗口。 - 监控主从延迟(如
info replication
中的lag
字段)。
面试官追问:Redis cluster 集群里边的 节点,怎么配置持久化?
在 Redis Cluster 集群中,每个节点 是独立的 Redis 实例,持久化配置 每个节点 在 配置文件(redis.conf
)中单独设置。Redis 提供两种持久化方式:RDB(快照)和 AOF(Append-Only File),可单独启用或同时启用。
(一)、核心持久化配置(适用于集群中所有节点)
以下配置需在每个节点的redis.conf
中设置(每个节点的配置文件独立,需分别修改)。
1. RDB 持久化配置(推荐基础配置)
RDB 通过定时生成内存快照(二进制文件)实现持久化,适合备份和灾难恢复。
# 1. 触发快照的条件(可配置多个,满足任一即触发)
# 格式:save <秒数> <修改次数>
save 60 1000 # 示例:60秒内有1000次修改则生成快照
save 300 10 # 300秒内有10次修改(配置多个,满足任一即触发)
save 900 1 # 900秒内有1次修改(配置多个,满足任一即触发)
# 2. 禁用RDB(如需完全禁用,注释所有save指令并添加)
# save ""
# 3. RDB文件名称(默认dump.rdb)
dbfilename dump-${port}.rdb # 建议添加端口号,避免同一服务器多节点文件冲突
# 4. RDB文件存储路径(需确保目录存在且Redis有写入权限)
dir /var/lib/redis-cluster/${port}/ # 每个节点建议使用独立目录(如按端口区分)
# 5. 快照生成失败时,是否停止接受写操作(推荐yes,防止数据丢失)
stop-writes-on-bgsave-error yes
# 6. 是否对RDB文件压缩(yes节省空间,no节省CPU,推荐yes)
rdbcompression yes
# 7. 是否对RDB文件进行校验(yes增加安全性,略耗CPU,推荐yes)
rdbchecksum yes
2. AOF 持久化配置(推荐与 RDB 结合使用)
AOF 通过记录所有写操作日志(文本指令)实现持久化,数据完整性更高(接近实时)。
# 1. 启用AOF(默认no,需手动开启)
appendonly yes
# 2. AOF文件名称(默认appendonly.aof)
appendfilename "appendonly-${port}.aof" # 建议添加端口号区分
# 3. AOF文件存储路径(与RDB相同,共享dir配置)
# dir /var/lib/redis-cluster/${port}/ # 已在RDB中配置,无需重复
# 4. AOF刷盘策略(核心参数,平衡性能与安全性)
# - always:每次写操作都刷盘(最安全,性能损耗大)
# - everysec:每秒刷盘一次(推荐生产环境,折中方案)
# - no:由操作系统决定刷盘时机(性能好,数据丢失风险高)
appendfsync everysec
# 5. AOF重写时是否暂停刷盘(推荐yes,避免重写与刷盘冲突影响性能)
no-appendfsync-on-rewrite yes
# 6. AOF自动重写触发条件(避免文件过大)
# 当AOF文件大小比上次重写后增长100%(即翻倍),且当前大小≥64MB时触发
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 7. AOF文件损坏时的处理(推荐yes,忽略错误部分继续加载)
aof-load-truncated yes
# 8. 启用RDB-AOF混合持久化(Redis 4.0+,推荐开启)
# 重写AOF时,文件开头为RDB快照,后续为增量AOF指令,兼顾RDB和AOF优点
aof-use-rdb-preamble yes
(二)、集群环境下的配置注意事项
1、每个节点独立配置:集群中每个节点(主 / 从)的redis.conf
是独立的,需分别设置持久化参数(尤其是dbfilename
和dir
,避免同一服务器上的节点文件冲突)。2、主从节点建议均开启持久化:
- 主节点开启:确保自身数据可持久化,防止主节点宕机后数据丢失。
- 从节点开启:防止从节点被选举为新主节点后,因自身无持久化导致重启后数据丢失。
3、避免持久化对集群性能的影响:
- RDB 的
bgsave
和 AOF 的bgrewriteaof
会 fork 子进程,可能短暂阻塞主进程(尤其内存大的节点)。建议在业务低峰期手动触发(如BGSAVE
、BGREWRITEAOF
命令),或调整自动触发条件。 - 若使用 AOF,
appendfsync everysec
是性价比最高的选择(每秒丢失最多 1 秒数据)。
4、定期备份持久化文件:无论 RDB 还是 AOF,都需定期将dir
目录下的持久化文件备份到独立存储(如异地备份),防止节点所在服务器故障导致文件丢失。
(三)、配置生效与验证
1、修改配置后生效:
- 重启节点:
redis-cli -h 节点IP -p 节点端口 shutdown
,再用redis-server /path/to/redis.conf
启动。 - 在线生效(部分参数):通过config set 命令临时修改(重启后失效,需同步到redis.conf),例如:
redis-cli -h 127.0.0.1 -p 6379 config set appendonly yes redis-cli -h 127.0.0.1 -p 6379 config rewrite # 将临时配置写入redis.conf```bash
```
2、验证配置:使用config get
命令查看当前配置,例如:
```bash
# 查看AOF是否启用
redis-cli -h 127.0.0.1 -p 6379 config get appendonly
# 查看RDB触发条件
redis-cli -h 127.0.0.1 -p 6379 config get save
3、检查持久化文件:查看dir
目录下是否生成dump-${port}.rdb
或appendonly-${port}.aof
文件,例如:
```bash
ls /var/lib/redis-cluster/6379/
(四)、尼恩来一个redis 推荐配置文件
生产环境中,Redis Cluster 建议同时启用 RDB 和 AOF,结合两者优势:
- RDB 适合定时备份和快速恢复(文件小,加载快)。
- AOF 适合保证数据完整性(丢失数据少)。
- 开启混合持久化(
aof-use-rdb-preamble yes
),让 AOF 文件同时包含 RDB 快照和增量指令,兼顾性能和安全性。
通过以上配置,可确保 Redis Cluster 在节点故障、重启时最大限度减少数据丢失,同时保证集群的稳定性。尼恩来一个redis 推荐配置文件,如下:
# ==========================================
# Redis 7.x Cluster 生产环境推荐配置模板
# 说明:每个集群节点需单独配置(端口/路径需对应修改)
# ==========================================
# ---------------------------
# 基础身份与路径配置
# ---------------------------
port 6379 # 节点端口(集群内节点端口需唯一)
daemonize no # 建议设为no,由systemd管理进程(更可靠)
pidfile /var/run/redis_6379.pid # PID文件路径
dir /data/redis/6379 # 数据文件(RDB/AOF)存储目录(需提前创建并授权)
logfile /data/redis/6379/redis.log # 日志文件路径(目录需与dir一致)
loglevel notice # 日志级别(notice:生产环境推荐,平衡详细度与性能)
# ---------------------------
# 集群核心配置
# ---------------------------
cluster-enabled yes # 启用集群模式
cluster-config-file nodes-6379.conf # 集群元数据文件(自动生成,无需手动修改)
cluster-node-timeout 5000 # 节点心跳超时时间(5秒,超时触发故障检测)
cluster-require-full-coverage no # 允许部分槽位不可用时仍提供服务(避免单点故障导致整体不可用)
cluster-migration-barrier 1 # 主节点至少保留1个从节点才允许其他从节点迁移(防止主节点无从可用)
cluster-replica-no-failover no # 允许从节点参与故障转移(默认no,保持启用)
# ---------------------------
# 安全配置
# ---------------------------
requirepass YourStrongPassword123! # 访问密码(建议包含大小写+数字+特殊字符,长度≥12位)
masterauth YourStrongPassword123! # 主从同步密码(必须与requirepass一致)
rename-command FLUSHALL "" # 禁用危险命令(根据业务需求调整,如FLUSHDB、KEYS等)
rename-command FLUSHDB ""
# ---------------------------
# 持久化配置(混合策略)
# ---------------------------
# AOF为主(高数据安全性)
appendonly yes
appendfilename "appendonly-6379.aof"
appendfsync everysec # 每秒刷盘(平衡性能与安全性,最多丢失1秒数据)
no-appendfsync-on-rewrite yes # AOF重写时暂停刷盘(减少IO冲突,重写期间仍可能丢失1秒数据)
auto-aof-rewrite-percentage 100 # AOF文件比上次重写后增长100%时触发重写
auto-aof-rewrite-min-size 64mb # AOF文件最小64MB才触发重写
aof-use-rdb-preamble yes # 启用RDB-AOF混合持久化(文件头部为RDB,尾部为增量指令)
aof-load-truncated yes # 加载AOF时忽略尾部错误(避免文件损坏导致启动失败)
# RDB为辅助(冷备份+快速恢复)
save 3600 1 # 1小时内有1次修改则生成快照(适合冷备份)
save1800 10 # 30分钟内10次修改
dbfilename dump-6379.rdb # RDB文件名(含端口区分)
rdbcompression yes # 启用RDB压缩(节省磁盘空间)
rdbchecksum yes # 启用RDB校验(防止文件损坏)
# ---------------------------
# 主从同步与数据安全
# ---------------------------
# 注意:Redis 5.0+已将slave参数统一改为replica,旧参数已废弃
min-replicas-to-write 1 # 主节点至少有1个从节点同步正常才接受写请求
min-replicas-max-lag 5 # 从节点同步延迟≤5秒视为“正常”
replica-serve-stale-data no # 从节点同步中断时拒绝读请求(避免返回过期数据)
repl-disable-tcp-nodelay yes # 禁用TCP延迟算法(减少主从同步延迟,轻微增加带宽)
repl-backlog-size 64mb # 主从断开后,主节点保留64MB的写操作缓冲区(加速重连后同步)
repl-backlog-ttl 3600 # 缓冲区无从节点连接时,保留1小时后释放
# ---------------------------
# 内存管理与淘汰策略
# ---------------------------
maxmemory 2gb # 节点最大可用内存(根据服务器配置调整,建议留20%余量)
maxmemory-policy noeviction # 内存满时拒绝写请求(集群模式禁用淘汰,避免数据不一致)
maxmemory-samples 5 # 淘汰策略采样数量(平衡精度与性能)
lazyfree-lazy-eviction yes # 异步释放内存(减少删除大键时的阻塞)
lazyfree-lazy-expire yes # 异步处理过期键删除
# ---------------------------
# 网络与性能优化
# ---------------------------
tcp-backlog 511 # TCP连接队列大小(需配合内核net.core.somaxconn)
timeout 0 # 客户端空闲超时(0表示永不超时)
tcp-keepalive 300 # 5分钟发送一次TCP保活探测(检测死连接)
client-output-buffer-limit normal 0 0 0 # 普通客户端无缓冲区限制(按需调整)
client-output-buffer-limit replica 512mb 128mb 60 # 从节点缓冲区:超过512MB或128MB持续60秒则断开
io-threads 4 # 启用4个IO线程(Redis 6.0+,值为CPU核心数的1/2最佳)
io-threads-do-reads yes # IO线程处理读操作(提升吞吐量)
# ---------------------------
# 慢查询与监控
# ---------------------------
slowlog-log-slower-than 10000 # 记录执行时间>10ms的命令(微秒)
slowlog-max-len 2048 # 慢查询日志最多保留2048条
latency-monitor-threshold 100 # 记录延迟>100ms的操作(便于排查性能问题)
# ---------------------------
# 系统级优化建议(需配合操作)
# ---------------------------
# 1. 内核参数(/etc/sysctl.conf):
# net.core.somaxconn = 1024
# vm.overcommit_memory = 1
# net.ipv4.tcp_max_tw_buckets = 65536
# 2. 禁用透明大页:
# echo never > /sys/kernel/mm/transparent_hugepage/enabled
# 3. 资源限制(/etc/systemd/system/redis.service):
# LimitNOFILE=1000000
# LimitNPROC=1000000
# 4. 监控重点:
# - cluster_info 集群状态
# - info replication 主从同步状态(lag值)
# - info memory 内存使用率
# - info persistence AOF/RDB持久化状态
二、扩展学习:AOF持久化原理
Redis提供了三种持久化方案
作为基础知识,需要 深入介绍一下 Redis提供了三种持久化方案:
- AOF(Append Only File):实时记录每一条写命令,恢复时“重播”命令就能还原数据。
- RDB(Redis DataBase):在指定时间点拍个“快照”,把当时的全量数据存到磁盘,恢复时直接加载快照。
- 混合持久化:结合AOF和RDB的优点,用RDB存全量数据,用AOF存增量命令,兼顾安全和性能。
先从AOP讲起
1、AOF工作原理
AOF(Append Only File)持久化通过实时记录每一条写命令到日志文件中,在服务重启时重新执行这些命令来恢复数据。与MySQL等数据库采用的写前日志(Write Ahead Log,WAL)不同,Redis AOF采用写后日志机制。写后日志的优势:
- 先执行命令再进行日志记录,避免了记录错误命令的可能性
- 不会阻塞当前的写操作执行
- 简化了日志记录的逻辑处理
写后日志的缺点:
- 如果执行完一个命令还没来得及写日志就宕机了会造成响应数据丢失。
- AOF 的写入由主线程处理,如果写入时出现较长耗时,那就会影响主线程处理后续的请求。
AOF通过记录每个写操作命令来持久化数据。当Redis重启时,会重新执行AOF文件中的所有命令,从而恢复数据状态。
2、AOF配置与开启方式
AOF功能默认关闭,需要通过以下方式开启:
# 配置文件方式(redis.conf)
appendonly yes
# 命令行动态配置
redis-cli config set appendonly yes
3、AOF写回策略
Redis提供了三种AOF写回策略,满足不同场景下的数据安全与性能需求:
策略 | 机制 | 优点 | 缺点 | 适用场景 |
Always | 同步写回,每条命令执行后立即刷盘 | 数据可靠性最高,几乎不丢失 | 性能影响大,每次写操作都需磁盘IO | 对数据安全要求极高的场景 |
Everysec | 每秒写回,异步刷盘 | 性能与可靠性平衡 | 可能丢失1秒内的数据 | 大多数业务场景的默认选择 |
No | 由操作系统控制写回时机 | 写入性能最佳 | 可靠性差,可能丢失大量数据 | 可容忍数据丢失的非关键业务 |
配置方式:
# 修改redis.conf配置文件
appendfsync everysec
# 或通过命令行设置
redis-cli config set appendfsync everysec
4、AOF 配置项
在 Redis 配置文件 redis.conf
中,AOF 持久化提供了多个可配置参数,用于精细控制 AOF 的行为和特性。下表对这些配置项进行了系统梳理和说明:
配置项 | 默认值 | 可选值 | 说明 |
appendonly | no | yes/no | 是否开启 AOF 持久化功能。 • no : 关闭 • yes : 开启 |
appendfilename | "appendonly.aof" | 自定义文件名 | 指定 AOF 文件的名称。 |
dir | ./ | 自定义目录路径 | 指定 AOF 文件(及 RDB 文件)的存储目录。 |
appendfsync | everysec | always/everysec/no | AOF 日志写回磁盘的策略: • always : 同步写回,每个写命令执行完立即刷盘,可靠性最高但性能影响大 • everysec : 每秒写回,在可靠性和性能之间取得平衡 • no : 由操作系统控制写回时机,性能最好但可靠性最差 |
no-appendfsync-on-rewrite | no | yes/no | 是否在 AOF 重写或 RDB 持久化期间,禁止主进程进行 AOF 刷盘: • no : 允许刷盘,可能因磁盘 IO 压力阻塞主线程 • yes : 禁止刷盘,避免阻塞但可能丢失更多数据 生产环境建议: 写操作多时设为 yes ,读操作多时设为 no |
auto-aof-rewrite-percentage | 100 | 正整数 | AOF 文件大小比上次重写后大小增长的百分比阈值,达到此阈值则触发重写。 例如设置为 100,表示当前 AOF 文件大小是上次重写后大小的 2 倍(即增长 100%)时触发。 |
auto-aof-rewrite-min-size | 64mb | 单位:kb, mb, gb | 触发 AOF 重写的最小文件大小。即使增长百分比达到要求,但文件大小未达到此值也不会触发重写。 |
aof-load-truncated | yes | yes/no | 当 Redis 启动时发现 AOF 文件被截断(可能因宕机导致最后一条命令不完整)是否继续加载: • yes : 截断不完整命令,正常启动 • no : 拒绝启动,需手动修复 AOF 文件 |
aof-use-rdb-preamble | yes | yes/no | 是否开启混合持久化模式(Redis 4.0+): • yes : AOF 重写时先以 RDB 格式写入全量数据,再追加增量 AOF 日志 • no : 仅使用纯 AOF 格式 |
提示:修改配置可通过直接编辑redis.conf
文件,或使用CONFIG SET parameter value
命令在线动态调整(重启后失效,需手动修改配置文件以持久化变更)。
5、AOF文件格式与内容
AOF文件以Redis协议格式记录命令,例如执行set testkey testvalue
后,AOF文件中会记录:
*3
$3
set
$7
testkey
$9
testvalue
*3
表示命令有3个部分$3
表示接下来的部分有3个字节("set")- 后续类似格式分别表示键和值
6、AOF 重写:解决日志膨胀的智能机制
6.1 为什么需要 AOF 重写?
让我们从一个实际场景入手:假设我们对同一个键 testkey
先后执行了多次写操作:
set testkey testvalue
set testkey value
在传统的 AOF 记录方式下,所有这些操作都会被完整记录在 AOF 文件中。但当我们进行数据恢复时,实际上只需要最后一条命令 set testkey value
就能恢复到最终状态,第一条命令成了"冗余数据"。这就是 AOF 重写要解决的核心问题:消除历史冗余命令,压缩文件体积。随着系统运行时间增长,AOF 文件中会积累大量这样的冗余记录,导致文件不断膨胀,不仅占用大量磁盘空间,还会影响数据恢复速度。
6.2 AOF 重写的工作原理
AOF 重写的核心思想很巧妙:不再分析旧的 AOF 文件,而是直接读取当前数据库状态,然后生成一条条能够重现当前数据状态的命令。举个例子,如果一个列表键经历了以下操作:最终列表状态为
["D", "E","F"]
。重写后,AOF 文件只需要记录:
LPUSH mylist “D”, “E”, "F"
这一条命令就能重现最终状态,相比原来的 6 条命令,压缩效果明显。
6.3 AOF 重写的执行流程
为了避免重写过程阻塞主线程,Redis 使用 fork 创建子进程来完成重写任务。下面是详细的执行流程:
- Redis 在接收到一条客户端发送过来的写命令后,会先执行该写命令,待命令执行成功后将该命令按照 Redis 通信协议格式写入 AOF 缓冲区。
- 根据设置的 AOF 写回策略,当满足写回条件时,将 AOF 缓冲区中的数据写入磁盘 AOF 文件中。
- 当 AOF 文件大小达到重写条件后,主进程 fork 出 bgrewriteaof 子进程,由子进程将内存中的数据重写为写命令写入临时文件。
- 若重写期间,主线程执行了新的写操作,主线程在将该写操作记录到 AOF 缓冲区的同时会将该写操作写入重写缓存区。
- 待子进程完成内存中数据的记录后,会将重写缓存区记录的数据一并写入临时文件。
- 最后利用临时文件替换原来的 AOF 文件。
重写期间的新写操作会同时写入两个缓冲区:
- AOF缓冲区:按正常流程同步到现有AOF文件
- 重写缓冲区:专门用于保存重写期间的新操作
当子进程完成重写后,主进程会将重写缓冲区的内容追加到新的AOF文件,确保数据完整性。这个流程的关键点在于:1、非阻塞设计:重写工作由子进程完成,主进程继续正常服务2、数据一致性保障:通过重写缓冲区确保重写期间的新写操作不丢失3、原子性替换:使用临时文件+重命名机制确保替换操作的原子性
6.4 重写触发条件与配置
AOF 重写支持手动和自动两种触发方式:手动触发:
# 立即启动AOF重写
redis-cli BGREWRITEAOF
自动触发条件(需同时满足):(1) 当前没有 RDB 持久化或 AOF 重写正在进行(2) AOF 文件大小 ≥ auto-aof-rewrite-min-size
(默认 64MB)(3) AOF 文件大小比上次重写后大小增长 ≥ auto-aof-rewrite-percentage
(默认 100%)配置示例:
# 最小重写大小阈值
auto-aof-rewrite-min-size 64mb
# 增长百分比阈值
auto-aof-rewrite-percentage 100
7、AOF优缺点分析
优点:(1)AOF 可以更好的保护数据不丢失,一般 AOF 会每隔1秒,通过一个后台线程执行 fsync 操作,最多丢失 1 秒钟的数据。(2)Redis 提供了 AOF 文件的重写机制,因此 AOF 日志文件不会膨胀的很大,并且在重写期间也不会影响客户端的读写。(3)AOF 文件中保存的是执行的指令,所以这个特性非常适合做灾难性的误操作紧急恢复。缺点:(1)由于 AOF 文件中记录的是写操作的命令,因此对于同一份数据来说,AOF 的日志文件通常要比 RDB 的数据快照文件要大。(2)AOF 开启之后,Redis 服务支持的写 QPS 会比 RDB 支持的写 QPS 低。
三、扩展学习:RDB持久化 原理
1、RDB核心概念
RDB(Redis DataBase)通过创建内存数据的时间点快照实现持久化。它将某一时刻的所有数据以二进制格式保存到磁盘文件中。
2、RDB触发方式
1. save命令(同步方式,不推荐生产使用)save
命令是主线程自己执行RDB,期间会完全阻塞Redis,不能处理任何客户端请求。如果数据量大,可能阻塞几秒甚至几分钟,生产环境绝对不能用。
redis-cli save
# 执行期间阻塞所有客户端请求
2. bgsave命令(异步方式,推荐使用)bgsave
是“background save”的缩写,主线程会fork
一个子进程,由子进程执行RDB,主线程继续处理请求。只有fork
子进程的瞬间会短暂阻塞(毫秒级),几乎不影响业务。
redis-cli bgsave
# 后台异步执行,仅fork阶段短暂阻塞
3. 自动触发在redis.conf
里配置save m n
,表示“m秒内有n次写操作”,就自动触发bgsave
。
# 3个条件,满足任意一个就触发bgsave
save 900 1 # 900秒(15分钟)内有1次写操作
save 300 10 # 300秒(5分钟)内有10次写操作
save 60 10000 # 60秒内有10000次写操作
比如QPS=1000的场景,60秒内会有60000次写操作,会触发bgsave
;如果QPS低,15分钟内有1次写操作也会触发,保证数据不会丢太多。4、三种触发方式的对比:
触发方式 | IO类型 | 是否阻塞主线程 | 优点 | 缺点 |
save | 同步 | 是(完全阻塞) | 不消耗额外内存(无fork) | 阻塞业务,生产禁用 |
bgsave | 异步 | 仅fork时阻塞 | 不影响业务 | fork子进程消耗内存(复制页表) |
自动触发 | 异步 | 仅fork时阻塞 | 无需手动操作 | 可能频繁触发(需合理配置m和n) |
3、RDB 配置项
在Redis配置文件(redis.conf)中,除了用于开启RDB功能的save配置项外,还提供了多个用于自定义RDB行为的配置参数。如下:
配置项 | 可选值 | 默认值 | 功能说明 | 性能与可靠性影响 |
stop-writes-on-bgsave-error | yes/no | yes | 当RDB持久化失败时是否停止接收写操作 | 设置为yes可避免数据不一致,但会增加服务不可用风险 |
rdbcompression | yes/no | yes | 是否对RDB文件进行LZF压缩 | 压缩减少磁盘空间占用,但增加CPU消耗 |
rdbchecksum | yes/no | yes | 是否在RDB文件末尾添加CRC64校验和 | 校验保证数据完整性,但增加少量CPU开销 |
dbfilename | 字符串 | dump.rdb | 指定RDB文件名 | 仅影响文件命名,无性能影响 |
dir | 路径 | ./ | 指定RDB文件存储目录 | 影响文件存储位置,建议使用高性能磁盘 |
rdb-del-sync-files | yes/no | no | 是否在没有持久化时删除同步文件 | 主要用于复制环境,对单实例影响较小 |
配置示例:
# Redis配置文件片段示例
stop-writes-on-bgsave-error yes # bgsave失败时拒绝写入,确保数据一致性
rdbcompression yes # 启用LZF压缩算法,减少磁盘占用
rdbchecksum yes # 启用CRC64校验,保证RDB文件完整性
dbfilename dump.rdb # 指定RDB文件名称
dir /var/lib/redis/ # 设置RDB文件存储路径
4、写时复制技术(Copy-On-Write)
COW详细内容参考:阿里面试:什么是COW(Copy-on-Write)技术? 探讨一下在mvcc、Java中的应用场景、实现原理及优缺点bgsave
子进程在写RDB的时候,主线程还在修改数据,会不会导致RDB文件里的数据混乱?答案是不会,因为Redis用了写时复制(Copy-On-Write,COW) 技术——这是操作系统提供的内存优化机制,核心逻辑是“读共享,写复制”。简单说:
- fork后,主线程和子进程共享同一块内存,子进程只读不写;
- 主线程要修改数据"C"时,会先复制一份该数据的“副本C`”,在副本上修改;
- 子进程写RDB用的还是原来的旧数据,保证快照是“fork时刻”的完整数据;
- 只复制“要修改的页”(内存按页管理,通常4KB/页),不是全量复制,内存消耗小。
5、RDB文件结构
RDB文件格式包含五个部分:1、SOF:5字节"REDIS"字符串,标识文件类型2、rdb_version:4字节版本号3、database:包含多个数据库的数据4、EOF:1字节结束标志5、check_sum:8字节校验和,用于验证文件完整性
6、RDB优缺点分析
优势:
- 数据恢复速度快(直接加载到内存)
- 文件体积小(二进制压缩格式)
- 最大化Redis性能(最小化持久化对性能的影响)
劣势:
- 可能丢失最后一次快照后的所有数据
- fork过程可能阻塞主进程(尤其在大数据集时)
- 不支持细粒度恢复(只能恢复到快照时间点)
四、混合持久化:兼顾安全与效率
1、什么是混合持久化
RDB 快照有个问题:两次快照之间的数据可能丢失,而快照太频繁又影响性能。所以 Redis 4.0 出了个混合持久化办法,能通过配置aof-use-rdb-preamble
开启。简单说就是:用 AOF 日志记录两次快照之间的操作,这样 AOF 文件不会太大,也不用频繁重写。比如,T1 到 T2 之间的修改用 AOF 记着,等第二次全量快照做好后,就把 AOF 日志清掉(因为修改已经进快照了),恢复数据时也不用再看日志了。
4.2 配置混合持久化
混合持久化需要配合AOF重写使用——开启后,新的AOF文件会变成“RDB+AOF”格式。方式1:修改redis.conf(永久生效)
# 开启混合持久化(Redis 4.0+支持,Redis 6.0+默认yes)
aof-use-rdb-preamble yes
# 同时确保AOF是开启的
appendonly yes
方式2:在线开启(临时生效)
# 1. 开启混合持久化
127.0.0.1:6379> config set aof-use-rdb-preamble yes
OK
# 2. 触发AOF重写,生成混合格式的AOF文件
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
# 3. 持久化配置(避免重启失效)
127.0.0.1:6379> config rewrite
OK
混合持久化配置后,AOF文件的结构是这样的:
- 前半部分:RDB格式的全量数据
- 后半部分:AOF格式的增量写命令
五、持久化方案选择与实战建议
方案对比与选型指南:
考量因素 | RDB | AOF | 混合模式 |
数据安全 | 可能丢失分钟级数据 | 最多丢失1秒数据 | 最多丢失1秒数据 |
恢复速度 | 快 | 慢 | 中等 |
文件大小 | 小 | 大 | 中等 |
性能影响 | 低(fork时短暂影响) | 中(依赖写回策略) | 中 |
适用场景 | 可容忍数据丢失 需要快速恢复 备份与灾难恢复 | 数据安全性要求高 可承受性能代价 | 生产环境推荐方案 平衡性能与安全 |
通用场景推荐配置:
# 开启混合持久化
aof-use-rdb-preamble yes
# RDB配置
save 900 1
save 300 10
save 60 10000
# AOF配置
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
数据敏感型场景:
appendfsync always # 每条命令都刷盘
性能优先场景:
appendfsync no # 由操作系统控制刷盘
转自
https://mp.weixin.qq.com/s/c1dZBIAImU4QP597aOe_6A