AOF 持久化最大的优势是可以缩短数据丢失的间隔,可以做到秒级的丢失率。RDB 会丢失上一个保存周期到目前的所有数据,只要没有触发 save 命令设置的 save seconds changes 阈值数据就会一直不被持久化。
struct redisServer { /* AOF buffer, written before entering the event loop */ sds aof_buf; } struct sdshdr { unsigned int len; unsigned int free; char buf[]; };aof_buf 是命令缓存区,采用 sds 结构缓存,每次当有命令被执行当时候都会写一次到 aof_buf 中。有几个配置用来控制 AOF 持久化的机制。
appendonly no appendfilename "appendonly.aof"appendonly 用来控制是否开启 AOF 持久化,appendfilename 用来设置 aof 文件名。
appendfsync always appendfsync everysec appendfsync noappendfsync 用来控制命令刷盘机制。现在操作系统都有文件 cache/buffer 的概念,所有的写入和读取都会走 cache/buffer,并不会每次都同步刷盘,因为这样性能一定会受影响。所以 redis 也提供了这个选项让我们来自己根据业务场景控制。
always :每次将 aof_buf 命令写入 aof 文件并且执行实时刷盘。
everysec :每次将 aof_buf 命令写入 aof 文件,但是每隔一秒执行一次刷盘。
no :每次将 aof_buf 命令写入 aof 文件不执行刷盘,由操作系统来自行控制。
AOF 也是采用后台子进程的方式进行,与主进程共享数据空间也就是 aof_buf,但是只要开始了 AOF 子进程之后 redis 事件循环文件事件处理器 会将之后的命令写入另外一个 aof_buf ,这样就可以做到平滑的切换。
AOF 会不断的追加命令进 aof 文件,随着时间和并发量的加大 aof 文件会极速膨胀,所以有必要对这个文件大小进行优化。redis 基于 rewrite 重写对文件进行压缩。
no-appendfsync-on-rewrite no/yes auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mbno-appendfsync-on-rewrite 控制是否在 bgrewriteaof 的时候还需要进行命令追加,如果追加可能会出现磁盘 IO 跑高现象。
上面说过,当 AOF 进程在执行的时候原来的事件循环还会正常的追加命令进 aof 文件,同时还会追加命令进另外一个 aof_buf ,用来做新 aof 文件的重写。这是两条并行的动作,如果我们设置成 yes 就不追加原来的 aof_buf 因为新的 aof 文件已经包含了之后进来的命令。
auto-aof-rewrite-percentage、auto-aof-rewrite-min-size 64mb 这两个配置前者是文件增长百分比来进行 rewrite ,后者是按照文件大小增长进行 rewrite 。