我所理解的 Redis AOF 持久化

408 阅读2分钟

介绍

Redis 是内存型数据库,一旦主进程退出就会造成数据丢失。它的持久化主要有两大机制,即 AOF 日志和 RDB 快照,本文主要关心 AOF 日志。

过程

Redis 执行完一个写命令后,将写命令以协议文本的形式追加到 AOF 缓冲区末尾,再通过同步策略来决定是否将 AOF 缓冲区中的内容写入 & 同步到 AOF 日志。

同步策略

AOF 机制提供了三个选择,也就是配置项 appendfsync 的三个可选值:

  • always:将 AOF 缓冲区中的所有内容写入同步AOF 日志。
  • everysec:将 AOF 缓冲区中的所有内容写入AOF 日志,如果上次同步 AOF 日志的时间距离现在超过 1 秒钟,那么对 AOF 日志进行同步
  • no:将 AOF 缓冲区中的所有内容写入到 AOF 日志,但并不对 AOF 日志进行同步, 何时同步由操作系统来决定。

三种策略的优缺点也显而易见了,always 可靠性高性能低、no 可靠性低性能高,everysec 取两者折中。

重写机制

AOF 日志是以文件的形式记录接收到的所有写命令。随着接收的写命令越来越多,文件体积会越来越大。这也就意味着会带来一些问题。

  • 操作系统对文件体积有限制,不能保存过大的文件。
  • 对体积比较大的文件进行追加写入,效率会降低。
  • AOF 日志体积过大,故障恢复过程缓慢。

为了解决上面的问题,Redis 提供了重写功能。通过该功能,Redis 可以创建一份新的 AOF 日志来代替现有的 AOF 日志。

  • 两份 AOF 日志所保存的数据库状态相同。
  • AOF 日志不会包含浪费空间的冗余命令。
  • AOF 日志体积小于等于原 AOF 日志。

重写过程

为什么要放在子进程里执行?

不会造成主线程阻塞,子进程进行 AOF 重写期间,主线程可以继续处理命令请求。

重写过程中有写命令,会造成数据不一致吗?

不会,Redis 维护了 AOF 重写缓冲区,在主线程创建重写子进程后开始使用。如果重写期间有写命令请求,Redis 会追加写入 AOF 缓冲区和 AOF重写缓冲区。当子进程完成创建新 AOF 日志后,主线程会将 AOF 重写缓冲区中的所有内容追加写入新 AOF 日志,此时新旧两份 AOF日志所保存的数据库状态完全一致。最后,用新 AOF 日志覆盖旧 AOF 日志,完成 AOF 日志重写操作。