Redis作为内存数据库,所有数据存储在物理内存中。服务器意外宕机或Redis进程崩溃时,内存中的数据将全部丢失。Redis提供RDB(快照)和AOF(追加日志)两种持久化机制,以及两者结合的混合持久化方案。数据库运维中,选择合适的持久化策略是数据备份恢复策略的关键环节,需要在数据安全性和性能开销之间找到平衡。
RDB快照持久化原理与配置
RDB通过fork子进程将内存数据以二进制格式写入磁盘文件。触发方式包括手动执行BGSAVE、配置定时触发、主从复制自动触发。RDB文件紧凑、恢复速度快,但存在数据窗口(最近一次快照后的增量数据丢失风险)。
# redis.conf RDB配置
# 定时快照触发规则:save <seconds> <changes>
# 3600秒内至少1个key变化则触发快照
save 3600 1
# 300秒内至少100个key变化
save 300 100
# 60秒内至少10000个key变化
save 60 10000
# 禁用RDB(注释或删除所有save行)
# save ""
# 快照文件名和路径
dbfilename dump.rdb
dir /data/redis/
# BGSAVE出错时停止写入(生产环境建议yes)
stop-writes-on-bgsave-error yes
# RDB文件LZF压缩(节省磁盘,增加CPU开销)
rdbcompression yes
# RDB文件校验和(防损坏,增加约10%写入开销)
rdbchecksum yes
# 手动触发RDB快照
redis-cli BGSAVE
# 查看快照状态
redis-cli INFO persistence
# 输出关键字段:
# rdb_bgsave_in_progress:0 - 是否正在执行BGSAVE
# rdb_last_save_time:1725686400 - 上次快照时间戳
# rdb_last_bgsave_status:ok - 上次快照状态
# rdb_last_bgsave_time_sec:2 - 上次快照耗时(秒)
# 同步快照(阻塞,生产环境禁用)
redis-cli SAVE
# RDB文件恢复:将dump.rdb放到dir配置的路径下,启动Redis自动加载
# 分析RDB文件内容
redis-check-rdb /data/redis/dump.rdb
AOF追加日志持久化原理与配置
AOF(Append Only File)记录所有写命令到日志文件。恢复时按顺序重放命令重建数据。AOF的数据安全性高于RDB,但文件体积更大、恢复速度更慢。
# redis.conf AOF配置
# 开启AOF
appendonly yes
# AOF文件名
appendfilename "appendonly.aof"
appenddirname "appendonlydir"
# 同步策略(核心配置)
# always - 每个写命令都fsync,最安全但性能最差
# everysec - 每秒fsync一次(推荐,最多丢失1秒数据)
# no - 由OS决定fsync时机,性能最好但数据安全性差
appendfsync everysec
# 重写期间禁用fsync(减少磁盘IO)
no-appendfsync-on-rewrite no
# AOF重写触发条件
# AOF文件大小比上次重写后大100%时触发
auto-aof-rewrite-percentage 100
# AOF文件最小重写大小
auto-aof-rewrite-min-size 64mb
# AOF重写时的fsync策略
aof-rewrite-incremental-fsync yes
# 手动触发AOF重写
redis-cli BGREWRITEAOF
# 查看AOF状态
redis-cli INFO persistence
# 输出关键字段:
# aof_enabled:1
# aof_rewrite_in_progress:0
# aof_rewrite_scheduled:0
# aof_last_rewrite_time_sec:1
# aof_current_size:1048576
# aof_base_size:524288
# AOF文件修复(文件损坏时)
redis-check-aof --fix /data/redis/appendonly.aof
# AOF文件截断修复
redis-check-aof --truncate-to-timestamp 1725686400 /data/redis/appendonly.aof
AOF重写机制详解
AOF文件持续增长会导致磁盘占用和恢复时间增加。AOF重写通过fork子进程扫描当前内存数据,生成最小命令集的新AOF文件,替换旧文件。
# AOF重写过程:
# 1. 主进程fork子进程
# 2. 子进程遍历内存生成新AOF文件
# 3. 主进程将fork后的增量写命令写入AOF缓冲区和AOF重写缓冲区
# 4. 子进程完成写入后通知主进程
# 5. 主进程将重写缓冲区内容追加到新AOF文件
# 6. 原子替换旧AOF文件
# Redis 7.0+ AOF多文件结构
# appendonlydir/
# ├── manifest.aof - 清单文件(记录AOF文件序列)
# ├── appendonly.aof.1.base.rdb - 基础文件(重写后的快照)
# ├── appendonly.aof.1.incr.aof - 增量文件(重写后的新命令)
# └── appendonly.aof.2.incr.aof - 下一次重写后的增量
混合持久化方案
Redis 4.0+支持混合持久化,AOF重写时将内存数据以RDB格式写入AOF文件头部,后续增量命令以AOF格式追加。结合了RDB的快速恢复和AOF的数据完整性。
# redis.conf 开启混合持久化
# aof-use-rdb-preamble yes (Redis 4.0-4.x)
# 或 Redis 5.0+默认开启
# 验证混合持久化
# 重写后的AOF文件前几个字节为REDIS(RDB格式标识)
head -c 10 /data/redis/appendonly.aof | xxd
# 00000000: 5245 4449 5330 3030 37 ... REDIS0007...
# 混合持久化AOF文件结构:
# [RDB格式的全量数据快照] + [AOF格式的增量命令]
# 恢复时先加载RDB部分(快),再重放AOF部分(补全增量)
持久化方案性能对比与选型
# 性能基准测试脚本
import redis
import time
r = redis.Redis(host='localhost', port=6379)
# 写入10万条数据测试性能
def benchmark_write(count=100000):
start = time.time()
for i in range(count):
r.set(f"bench:key:{i}", f"value:{i}" * 50)
elapsed = time.time() - start
return count / elapsed
# 仅RDB模式吞吐量
r.config_set('appendonly', 'no')
r.config_set('save', '3600 1') # 降低RDB频率
throughput_rdb = benchmark_write()
print(f"仅RDB: {throughput_rdb:.0f} ops/s")
# AOF everysec模式
r.flushall()
r.config_set('appendonly', 'yes')
r.config_set('appendfsync', 'everysec')
throughput_aof = benchmark_write()
print(f"AOF everysec: {throughput_aof:.0f} ops/s")
# AOF always模式
r.flushall()
r.config_set('appendfsync', 'always')
throughput_always = benchmark_write()
print(f"AOF always: {throughput_always:.0f} ops/s")
# 典型结果(单线程SET 10万条):
# 仅RDB: ~85000 ops/s
# AOF everysec: ~78000 ops/s (降低约8%)
# AOF always: ~12000 ops/s (降低约86%)
三种方案的对比:
仅RDB:写入性能最高,恢复速度快(直接加载二进制文件),数据丢失窗口大(取决于save配置)。适合缓存场景或可容忍分钟级数据丢失的业务。
仅AOF(everysec):写入性能降低约8-10%,数据丢失窗口1秒,恢复速度慢(需重放命令)。适合对数据完整性要求高的业务,如用户操作记录、订单状态。
混合持久化:AOF重写时使用RDB格式,恢复速度接近纯RDB,数据完整性等同AOF。生产环境推荐方案,兼顾性能和数据安全。
从节点持久化与主从复制持久化策略
# 生产环境推荐配置
# 主节点:关闭持久化(由从节点负责),最大化写入性能
# 主节点 redis.conf
save ""
appendonly no
# 从节点:开启AOF + RDB,作为数据备份源
# 从节点 redis.conf
save 3600 1
save 300 100
appendonly yes
appendfsync everysec
# 主从复制配置
# 从节点 redis.conf
replicaof 192.168.1.10 6379
masterauth <password>
replica-read-only yes
# 从节点持久化由自身控制,不受主节点影响
# 当主节点故障切换时,新主节点需开启持久化
# Redis Sentinel自动故障切换
# sentinel.conf
sentinel monitor mymaster 192.168.1.10 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
数据备份与恢复实战
# 定时备份脚本(crontab每小时执行)
#!/bin/bash
BACKUP_DIR="/data/redis-backup"
DATE=$(date +%Y%m%d%H%M)
REDIS_DIR="/data/redis"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 触发BGSAVE并等待完成
redis-cli BGSAVE
while [ $(redis-cli INFO persistence | grep rdb_bgsave_in_progress | tr -d '
') != "rdb_bgsave_in_progress:0" ]; do
sleep 1
done
# 备份RDB和AOF文件
cp $REDIS_DIR/dump.rdb $BACKUP_DIR/dump-$DATE.rdb
cp -r $REDIS_DIR/appendonlydir $BACKUP_DIR/appendonlydir-$DATE
# 保留最近7天备份
find $BACKUP_DIR -name "*.rdb" -mtime +7 -delete
find $BACKUP_DIR -name "appendonlydir-*" -mtime +7 -exec rm -rf {} +
echo "Redis备份完成: $DATE"
# crontab配置
# 0 * * * * /opt/scripts/redis-backup.sh >> /var/log/redis-backup.log 2>&1
# 灾难恢复流程
# 1. 停止Redis
redis-cli SHUTDOWN NOSAVE
# 2. 清空数据目录
rm -rf /data/redis/appendonlydir
rm -f /data/redis/dump.rdb
# 3. 恢复备份文件
cp /data/redis-backup/dump-202609071200.rdb /data/redis/dump.rdb
cp -r /data/redis-backup/appendonlydir-202609071200 /data/redis/appendonlydir
# 4. 启动Redis(自动加载RDB和重放AOF)
redis-server /etc/redis/redis.conf
# 5. 验证数据
redis-cli DBSIZE
redis-cli INFO persistence
fork耗时监控:RDB和AOF重写都需要fork子进程,大内存实例fork耗时可能达到秒级,期间主进程阻塞。通过INFO stats查看latest_fork_usec,超过100ms需要关注。内存超过20GB的实例建议使用多实例分片替代单实例大内存。
磁盘IO监控:AOF写入产生持续的磁盘IO。使用iostat监控磁盘util,持续高于80%会导致fsync延迟增加。SSD是Redis持久化的基本要求,机械磁盘场景建议降低appendfsync频率或关闭AOF。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/redis-chi-jiu-hua-ji-zhi-shi-zhan-rdb-yu-aof-pei-zhi-xuan/