Redis 持久化
持久化是将内存中的数据保存到磁盘的过程。Redis 提供了 RDB 和 AOF 两种持久化方式,本章将详细介绍这两种方式的原理和配置。
持久化概述
┌─────────────────────────────────────────────────────────────┐
│ Redis 持久化方式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Redis 内存数据 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ RDB 快照 │ │ AOF 日志 │ │
│ │ 二进制文件 │ │ 文本文件 │ │
│ │ 定时保存 │ │ 追加写入 │ │
│ │ 恢复速度快 │ │ 数据更安全 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
RDB 持久化
RDB(Redis Database)是将某一时刻的内存数据保存到磁盘的二进制文件(默认为 dump.rdb)。
RDB 工作原理
┌─────────────────────────────────────────────────────────────┐
│ RDB 快照流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 客户端触发 BGSAVE 命令 │
│ │ │
│ 2. Redis 主进程 fork 子进程 │
│ │ │
│ 3. 子进程将内存数据写入临时 RDB 文件 │
│ │ │
│ 4. 子进程完成,替换旧的 RDB 文件 │
│ │ │
│ 5. 主进程继续处理客户端请求 │
│ │
│ 注意:fork 使用写时复制(Copy-on-Write)技术 │
│ │
└─────────────────────────────────────────────────────────────┘
RDB 配置
# redis.conf 配置
# 触发快照的条件
# save <秒> <变化次数>
save 900 1 # 900 秒内有 1 次变化
save 300 10 # 300 秒内有 10 次变化
save 60 10000 # 60 秒内有 10000 次变化
# 禁用 RDB(注释掉所有 save 或设置空字符串)
# save ""
# RDB 文件名
dbfilename dump.rdb
# 数据目录
dir /var/lib/redis
# 压缩(默认开启)
rdbcompression yes
# 校验和(默认开启)
rdbchecksum yes
# RDB 文件存储失败时是否停止写入
stop-writes-on-bgsave-error yes
RDB 命令
# 手动触发快照(后台执行)
BGSAVE
# 手动触发快照(前台执行,会阻塞)
SAVE
# 获取上次保存时间
LASTSAVE
# 查看持久化状态
INFO persistence
RDB 优缺点
优点:
- 文件紧凑,适合备份
- 恢复速度快
- 对性能影响小(子进程执行)
- 适合灾难恢复
缺点:
- 数据安全性较低(可能丢失几分钟数据)
- fork 大数据集时可能阻塞
AOF 持久化
AOF(Append Only File)记录所有写操作命令,恢复时重新执行这些命令。
AOF 工作原理
### AOF 工作流程 (Redis 7.0+)
从 Redis 7.0 开始,AOF 架构演进为 **Multi-Part AOF**,大大降低了重写(Rewrite)的开销:
- **Base AOF**:主要的 AOF 文件,代表了开始重写时刻的数据快照。
- **Incremental AOF**:在重写过程中产生的增量日志。
- **Manifest File**:追踪并管理这些 AOF 文件。
**优势**:不再需要由于重写导致的大量内存写时复制(COW)开销,数据持久化更加平稳且高效。
AOF 配置
# redis.conf 配置
# 启用 AOF
appendonly yes
# AOF 文件名
appendfilename "appendonly.aof"
# AOF 目录(Redis 7.0+)
appenddirname "appendonlydir"
# 同步策略
# always : 每次写入都同步,最安全但最慢
# everysec : 每秒同步一次(推荐)
# no : 由操作系统决定,最快但不安全
appendfsync everysec
# 重写期间是否禁用 fsync
no-appendfsync-on-rewrite no
# AOF 重写触发条件
auto-aof-rewrite-percentage 100 # 文件比上次重写后增长 100%
auto-aof-rewrite-min-size 64mb # 文件最小 64MB
# 加载损坏的 AOF 文件是否继续
aof-load-truncated yes
# 使用 RDB-AOF 混合格式(Redis 4.0+)
aof-use-rdb-preamble yes
AOF 重写
AOF 文件会随着写操作不断增长,重写可以压缩文件大小:
# 手动触发重写
BGREWRITEAOF
# 查看重写状态
INFO persistence
重写原理:
- fork 子进程
- 子进程将当前内存数据写入临时文件
- 主进程继续记录新写入到重写缓冲区
- 子进程完成后,主进程追加重写缓冲区
- 替换旧 AOF 文件
AOF 优缺点
优点:
- 数据更安全(最多丢失 1 秒数据)
- AOF 文件可读,便于分析
- 文件损坏可修复
缺点:
- 文件体积较大
- 恢复速度较慢
- 对性能有影响
RDB 与 AOF 对比
| 特性 | RDB | AOF |
|---|---|---|
| 数据安全性 | 较低(分钟级丢失) | 较高(秒级丢失) |
| 文件大小 | 小 | 大 |
| 恢复速度 | 快 | 慢 |
| 系统资源消耗 | 低(fork 时) | 较高(持续写入) |
| 文件可读性 | 二进制 | 文本 |
| 适用场景 | 备份、主从复制 | 数据安全要求高 |
混合持久化
Redis 4.0 引入混合持久化,结合 RDB 和 AOF 的优点:
# 启用混合持久化
aof-use-rdb-preamble yes
工作原理:
- AOF 重写时,先写入 RDB 格式的快照
- 然后追加增量的 AOF 命令
- 恢复时先加载 RDB 部分,再执行 AOF 命令
持久化配置建议
场景一:纯缓存(可接受数据丢失)
# 关闭持久化
save ""
appendonly no
场景二:数据安全要求高
# 开启 AOF
appendonly yes
appendfsync everysec
# 也保留 RDB 用于备份
save 900 1
save 300 10
场景三:平衡方案
# 开启 AOF 和混合持久化
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
# RDB 用于快速重启和备份
save 900 1
save 300 10
save 60 10000
数据恢复
RDB 恢复
# 1. 停止 Redis
redis-cli shutdown
# 2. 将 dump.rdb 复制到数据目录
cp /backup/dump.rdb /var/lib/redis/
# 3. 启动 Redis
redis-server /etc/redis/redis.conf
AOF 恢复
# 1. 停止 Redis
redis-cli shutdown
# 2. 复制 AOF 文件
cp /backup/appendonly.aof /var/lib/redis/
# 3. 修复损坏的 AOF(如需要)
redis-check-aof --fix appendonly.aof
# 4. 启动 Redis
redis-server /etc/redis/redis.conf
从 RDB 切换到 AOF
# 在线切换(Redis 2.2+)
redis-cli CONFIG SET appendonly yes
redis-cli CONFIG SET save ""
# 持久化配置
redis-cli CONFIG REWRITE
备份策略
#!/bin/bash
# Redis 备份脚本
BACKUP_DIR="/backup/redis"
DATE=$(date +%Y%m%d_%H%M%S)
# 创建备份目录
mkdir -p $BACKUP_DIR
# 触发 RDB 快照
redis-cli BGSAVE
# 等待快照完成
sleep 5
# 复制 RDB 文件
cp /var/lib/redis/dump.rdb $BACKUP_DIR/dump_$DATE.rdb
# 压缩
gzip $BACKUP_DIR/dump_$DATE.rdb
# 删除 7 天前的备份
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete
echo "Backup completed: dump_$DATE.rdb.gz"
小结
本章我们学习了:
- RDB 持久化:快照方式,恢复快但可能丢数据
- AOF 持久化:日志方式,数据安全但文件大
- 混合持久化:结合两者优点
- 配置建议:根据场景选择合适策略
- 数据恢复:RDB 和 AOF 的恢复方法
练习
- 配置 RDB 持久化并手动触发快照
- 配置 AOF 持久化并观察文件变化
- 模拟 Redis 重启并恢复数据
- 编写自动备份脚本