Redis持久化机制实战:RDB与AOF配置选型与混合持久化方案

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/

(0)
小编小编
上一篇 9小时前
下一篇 9小时前

相关推荐