Redis Persistence
Based on Redis 7.0.11.
Redis 提供了四种持久化的方式:
- No persistence:不做持久化处理,用得较少。
- RDB:对缓存做全量 point-in-time 快照,生成的 *.rdb 文件非常紧凑,加载性能高,非 human readable。
- AOF:对每个 write operation 进行记录,通过 replay 重新生成当前缓存状态,记录按照 RESP 格式存储,human readable。
- RDB + AOF:结合 RDB 与 AOF。
RDB
命令&配置
SAVE
在当前进程生成快照,会阻塞服务;BGSAVE
在子进程中生成快照,不会阻塞服务。
除手动执行 SAVE
和 BGSAVE
,Redis 允许配置 BGSAVE
自动执行的条件:
1 | save M N # At lease N changes in the last M seconds |
满足多个条件中任意一条即可自动执行 BGSAVE
。
BGSAVE 执行过程
- Fork 子进程
- 子进程将数据写入临时 RDB 文件
- 子进程将临时 RDB 文件重命名替换当前 RDB 文件
- 子进程退出
- 父进程处理子进程 exitcode
1 | if server.child_type == CHILD_TYPE_RDB: |
Pros
- RDB 文件紧凑
- RDB 文件可以传输到其它机器上恢复
- 高性能,子进程 fork 出来后父进程照常处理请求,不会 disk I/O
Cons
- RDB 是整个数据库的快照,这决定了其无法做到非常高频地备份出快照。在 Redis 意外退出时,至少丢失数分钟的数据。
- 当数据库很大时,fork 子进程也将会比较耗时
- 执行快照过程中,如果父进程接收大量写请求,将导致大量的内存页拷贝。
AOF(Append-only file)
1 | appendonly yes |
开启 AOF 后,Redis 每收到一条写命令就会将该命令写入 AOF,Redis 重启时就可以重放 AOF 文件恢复数据。当 AOF 增长到一定大小时就需要进行重写,减小文件大小。
rewrite 过程
BGREWRITEAOF
。
- flush
aof_buf
,调用fsync
- 创建新的 incremental AOF 文件记录后续写命令
- Fork 子进程
- 子进程将当前数据库以 AOF 格式写入 temp BASE file
- 父进程 rename(temp BASE file, BASE file) 并与 incremental AOF 构建一个新的 manifest 文件
Pros
- 相比 RDB 有更优 durability,可做到秒级的数据备份
- AOF 使用 RESP 协议记录,易于直接阅读
Cons
- AOF 文件通常比 RDB 文件大
appendfsync everysec
对性能有轻微影响,实际并不明显
RDB + AOF
Redis 5 中默认开启
RDB + AOF 结合了 RDB 和 AOF 的优点,此时整体格式变为:[RDB] + [AOF],在 AOF 重写子进程中,不再是以 RESP 协议导出数据库到 BASE file,而是 RDB,即 BASE AOF file 中保存了 RDB 格式的数据。
Key takeaways
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 爱吃胡萝卜!