Redis持久化存储详解
一、核心持久化机制
Redis提供两种主要持久化方式:RDB(快照) 和 AOF(追加文件),以及两者的混合模式。
RDB(Redis Database)快照持久化
工作原理
RDB通过创建数据集的二进制快照进行持久化,默认保存在dump.rdb文件中。
配置示例(redis.conf)
# 保存策略(每15分钟至少1次修改)
save 900 1
# 每5分钟至少10次修改
save 300 10
# 每1分钟至少10000次修改
save 60 10000
# RDB文件名
dbfilename dump.rdb
# 工作目录
dir /var/lib/redis
# 压缩RDB文件
rdbcompression yes
# 启用CRC64校验
rdbchecksum yes
手动触发命令
# 阻塞式保存(生产环境避免使用)
127.0.0.1:6379> SAVE
OK
# 后台异步保存(推荐)
127.0.0.1:6379> BGSAVE
Background saving started
RDB文件结构
+---------+---------+---------+-----+---------+
| REDIS | RDB版本 | 数据库 | ... | EOF |
| 魔数(5字节) | (4字节) | 内容 | | (1字节) |
+---------+---------+---------+-----+---------+
AOF(Append Only File)日志持久化
工作原理
AOF记录所有写操作命令,以Redis协议格式保存到文件。
配置示例
# 启用AOF
appendonly yes
# AOF文件名
appendfilename "appendonly.aof"
# 同步策略(推荐每秒)
appendfsync everysec
# 重写时是否同步
no-appendfsync-on-rewrite no
# 触发重写的增长百分比
auto-aof-rewrite-percentage 100
# 触发重写的最小大小
auto-aof-rewrite-min-size 64mb
AOF重写过程
def bgrewriteaof():
# 1. 创建子进程
child_pid = fork()
if child_pid == 0: # 子进程
# 2. 创建临时AOF文件
temp_file = create_temp_aof()
# 3. 遍历数据库,写入当前状态
for db in databases:
for key in db:
write_command(temp_file, "SET", key, db[key])
# 4. 将重写期间的新命令追加到文件
append_rewrite_buffer(temp_file)
# 5. 原子替换旧AOF文件
rename(temp_file, "appendonly.aof")
exit(0)
else: # 主进程
# 记录重写开始时间
start_time = time.now()
# 继续处理客户端请求
while True:
# 处理请求...
# 将新命令写入AOF缓冲区和重写缓冲区
write_to_buffers(new_command)
AOF文件修复
# 修复损坏的AOF文件
$ redis-check-aof --fix appendonly.aof
# 修复前的备份
0x0000: *2 $6 SELECT $1 0
0x0013: *3 $3 set $4 name $5 Alice
0x002b: *3 $3 set $4 age $2 30 # 损坏行
# 修复后
0x0000: *2 $6 SELECT $1 0
0x0013: *3 $3 set $4 name $5 Alice
# 损坏行被移除
混合持久化(Redis 4.0+)
配置
aof-use-rdb-preamble yes
文件结构
+---------+---------+---------+-----+---------+
| RDB | AOF | AOF | ... | AOF |
| 数据快照 | 追加命令1 | 追加命令2 | | 追加命令N |
+---------+---------+---------+-----+---------+
二、持久化操作与监控
命令行操作
# 查看持久化状态
127.0.0.1:6379> INFO PERSISTENCE
# Output:
# aof_enabled:1
# aof_rewrite_in_progress:0
# rdb_last_bgsave_status:ok
# 手动触发AOF重写
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
# 获取当前配置
127.0.0.1:6379> CONFIG GET *append*
1) "appendonly"
2) "yes"
3) "appendfsync"
4) "everysec"
持久化监控脚本
import redis
import time
def monitor_persistence(r):
while True:
info = r.info('persistence')
# 检查RDB状态
rdb_status = "OK" if info['rdb_last_bgsave_status'] == 'ok' else "ERROR"
print(f"RDB Status: {rdb_status}, Last save: {info['rdb_last_save_time']}")
# 检查AOF状态
aof_status = "OK" if info['aof_last_bgrewrite_status'] == 'ok' else "ERROR"
print(f"AOF Status: {aof_status}, Size: {info['aof_current_size']/1024/1024:.2f}MB")
# 检查重写状态
if info['aof_rewrite_in_progress']:
print(f"AOF rewrite in progress: {info['aof_rewrite_buffer_length']} commands buffered")
time.sleep(60)
if __name__ == "__main__":
r = redis.Redis(host='localhost', port=6379)
monitor_persistence(r)
三、数据恢复流程
恢复优先级
恢复操作步骤
# 1. 停止Redis服务
$ redis-cli shutdown
# 2. 备份当前数据文件
$ cp /var/lib/redis/dump.rdb /backup/dump-$(date +%F).rdb
$ cp /var/lib/redis/appendonly.aof /backup/appendonly-$(date +%F).aof
# 3. 恢复RDB文件
$ mv /backup/dump-restore.rdb /var/lib/redis/dump.rdb
# 4. 恢复AOF文件(可选)
$ mv /backup/appendonly-restore.aof /var/lib/redis/appendonly.aof
# 5. 修改文件权限
$ chown redis:redis /var/lib/redis/*
# 6. 启动Redis
$ systemctl start redis-server
# 7. 验证数据
$ redis-cli DBSIZE
(integer) 123456 # 预期的键数量
四、性能优化与故障处理
性能优化策略
-
RDB优化:
# 禁用不必要的保存规则 save "" # 使用现代Linux系统(优化fork性能) # 配置大页内存 echo never > /sys/kernel/mm/transparent_hugepage/enabled -
AOF优化:
# 使用everysec策略(默认) appendfsync everysec # 增加重写缓冲区大小 aof-rewrite-buffer-size 128mb # 使用SSD存储 dir /ssd/redis-data
常见故障处理
1. OOM(内存不足)错误
场景:执行BGSAVE时因fork失败导致
Can't save in background: fork: Cannot allocate memory
解决方案:
# 检查系统配置
$ sysctl vm.overcommit_memory
vm.overcommit_memory = 1 # 应设置为1
# 增加交换空间
$ sudo fallocate -l 4G /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
# 减少Redis最大内存
127.0.0.1:6379> CONFIG SET maxmemory 8gb
2. AOF文件损坏
症状:Redis启动失败,日志报"AOF is not valid"
修复步骤:
# 1. 创建备份
$ cp appendonly.aof appendonly.bak
# 2. 修复文件
$ redis-check-aof --fix appendonly.aof
# 3. 验证修复后文件
$ head -n 20 appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
...
3. RDB生成缓慢
优化方案:
# 降低保存频率
save 3600 1 # 1小时内至少1次修改
save 86400 10 # 1天内至少10次修改
# 禁用压缩(CPU紧张时)
rdbcompression no
# 使用外部工具并行压缩
rdbcompression no
五、生产环境最佳实践
部署架构
配置推荐
# 混合持久化配置
appendonly yes
aof-use-rdb-preamble yes
appendfsync everysec
# RDB配置
save 3600 1 # 每小时保存
save 86400 10 # 每天保存
rdbcompression yes
# 内存管理
maxmemory 16gb
maxmemory-policy volatile-lru
# 安全配置
requirepass "StrongPassword123!"
rename-command FLUSHDB ""
备份策略
# 每日全量备份
0 2 * * * redis-cli BGSAVE && cp /var/lib/redis/dump.rdb /backup/dump-$(date +\%F).rdb
# 每小时AOF备份
0 * * * * cp /var/lib/redis/appendonly.aof /backup/aof/appendonly-$(date +\%H).aof
# 异地备份
0 3 * * * aws s3 cp /backup/dump-$(date +\%F).rdb s3://redis-backup/
灾难恢复测试
import redis
import subprocess
def disaster_recovery_test():
# 1. 创建测试数据
r = redis.Redis(password='StrongPassword123!')
for i in range(10000):
r.set(f'key:{i}', f'value-{i}')
# 2. 模拟故障
r.shutdown()
# 3. 恢复最新备份
subprocess.run(['cp', '/backup/latest.rdb', '/var/lib/redis/dump.rdb'])
subprocess.run(['systemctl', 'start', 'redis-server'])
# 4. 验证数据
recovered = redis.Redis(password='StrongPassword123!')
assert recovered.dbsize() == 10000
print("Disaster recovery test passed!")
if __name__ == "__main__":
disaster_recovery_test()
六、总结与选择指南
持久化方案选择矩阵
| 需求 | 推荐方案 | 配置要点 |
|---|---|---|
| 最大化性能 | RDB | save "", rdbcompression no |
| 最小化数据丢失 | AOF(always) + 混合持久化 | appendfsync always, aof-use-rdb-preamble yes |
| 快速重启恢复 | 混合持久化 | aof-use-rdb-preamble yes, rdbcompression yes |
| 有限磁盘空间 | RDB | 调整save间隔,增加压缩比 |
| 大数据集(>10GB) | RDB + 副本 | 增加repl-backlog-size, 优化fork性能 |
关键决策因素
- 数据重要性:金融数据使用AOF(always),缓存数据使用RDB
- 恢复时间目标(RTO):RDB恢复更快,适合大型数据集
- 恢复点目标(RPO):AOF提供秒级数据保护
- 系统资源:内存充足时使用混合模式,CPU受限时使用RDB
- 运维复杂性:AOF需要更多监控和管理
通过合理配置RDB和AOF,结合混合持久化模式,Redis可以在各种场景下实现性能与数据安全的最佳平衡。
2558

被折叠的 条评论
为什么被折叠?



