1. 为什么需要持久化
Redis 是内存数据库,进程退出后数据全部丢失。持久化将内存数据保存到磁盘,用于数据备份、灾难恢复和进程重启后的数据恢复。
2. RDB(Redis Database)快照
2.1 触发方式
# 手动触发
SAVE # 同步保存,阻塞主线程(生产不用)
BGSAVE # 后台异步保存,fork 子进程
# 自动触发(redis.conf)
save 900 1 # 900 秒内至少 1 个 key 变化 → 触发 BGSAVE
save 300 10 # 300 秒内至少 10 个 key 变化
save 60 10000 # 60 秒内至少 10000 个 key 变化
save "" # 禁用 RDB
2.2 Copy-On-Write 原理
BGSAVE 执行时:
1. 主进程 fork() 子进程
│
├── 父进程(Redis 主线程)──→ 处理客户端请求
│ │
│ 写入 key A ──→ 页面被修改 ──→ COW 复制页面
│ │ │
│ 新数据 ──→ 新页 旧页(子进程读取)
│
└── 子进程 ──→ 读取内存页 ──→ 写入 RDB 文件
COW 开销:fork 时只需复制页表,无需复制全部内存
实际额外内存 ≈ 写入操作涉及的数据量
2.3 RDB 优缺点
| 优点 | 缺点 |
|---|---|
| 文件紧凑,备份和传输方便 | 可能丢失两次快照间的数据 |
| 恢复速度快(直接加载) | 大数据量时 fork 可能耗时较长 |
| 对运行时性能影响小 |
3. AOF(Append Only File)
3.1 写入策略
# 同步策略
appendfsync always # 每条命令 fsync → 最安全,性能最差
appendfsync everysec # 每秒 fsync → 默认,最多丢 1 秒数据
appendfsync no # 由 OS 决定 → 最快,最不安全
# 在 rewrite 期间是否不 fsync(减少 IO 压力)
no-appendfsync-on-rewrite yes
3.2 AOF 重写(Rewrite)
AOF 持续追加会不断膨胀,重写将内存中的最新数据生成精简的命令集。
BGREWRITEAOF # 手动触发重写
# 自动重写条件
auto-aof-rewrite-percentage 100 # AOF 增长超过上次重写后 100%
auto-aof-rewrite-min-size 64mb # 最小 64MB 才重写
重写流程:
1. fork 子进程,扫描内存生成新 AOF 文件
2. 父进程在此期间的新写入写入「AOF 重写缓冲区」
3. 子进程完成后,父进程将重写缓冲区的命令追加到新 AOF
4. 原子替换旧 AOF 文件
4. 混合持久化(Redis 4.0+)
aof-use-rdb-preamble yes # 默认开启
重写后的 AOF 文件格式:
┌─────────────────────────────────────────┐
│ RDB 格式头部(二进制) │ ← 全量数据快照
│ 快速加载整个数据集 │
├─────────────────────────────────────────┤
│ AOF 格式命令(文本) │ ← 重写后的增量命令
│ 保证重写期间的数据不丢失 │
└─────────────────────────────────────────┘
恢复时:
1. 读取 RDB 部分 → 快速加载全量数据
2. 执行 AOF 部分的命令 → 补齐增量数据
5. 选型与生产建议
| 场景 | 推荐 | 原因 |
|---|---|---|
| 纯缓存(可重建) | RDB + 禁用 AOF | 内存为王,重启后重建 |
| 允许分钟级丢失 | RDB only | 简单、恢复快 |
| 不能丢数据 | AOF everysec | 最多丢 1 秒 |
| 生产推荐 | RDB + AOF 混合 | 兼顾恢复速度和数据安全 |
# 生产配置示例
save 900 1
save 300 10
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 128mb
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。