Redis 持久化机制 AOF
前言
Redis 有两种持久化机制,分别是 RDB 与 AOF 本篇文章将介绍 AOF 的执行过程与应用。
1. AOF 简介
AOF (Append only file) 持久化是以独立日志的方式记录每次写命令,重启时再重新读取文件中的命令,以达到恢复数据的目的。AOF 主要是为了解决数据持久化的实时性。
3. 参数设置
2.1 开启 AOF
开启 AOF 功能需要设置参数:appendonly yes 下方是查询参数语句:
127.0.0.1:6379> config get appendonly 1) "appendonly" 2) "no"
2.2 保存路径
默认文件名为:appendonly.aof 保存的路径与 RDB 配置一致,通过 dir 参数配置:
27.0.0.1:6379> config get dir 1) "dir" 2) "/usr/local/redis-5.0.0"
2.3 文件同步
Redis 提供三种 AOF 缓冲区同步策略,由 appendfsync 参数控制,具体含义将在 3.2 文件同步策略介绍。
127.0.0.1:6379> config get appendfsync 1) "appendfsync" 2) "everysec"
2.4 日志重写
AOF 日志文件过大,可触发重写机制,达到收缩日志目的,具体含义将在 3.3 日志重写机制介绍。
127.0.0.1:6379> config get auto-aof-* 1) "auto-aof-rewrite-percentage" 2) "100" 3) "auto-aof-rewrite-min-size" 4) "67108864"
3. AOF 实现解析
3.1 写入流程
我们熟悉的日志同步机制,例如 WAL 日志优先写,在实际写数据前,先修改的数据记录到文件中,便于故障恢复。Redis AOF 机制正好相反,它属于 “写后” 日志,先将命令执行把数据写入内存,再将命令写入日志。
这样做有两个优势:
1)避免语法检测带来的开销,命令先执行成功才会写入日志。
2)命令执行后才写入日志,不会堵塞当前写入操作。
AOF 命令写入使用的是文本协议格式,具有较好的兼容性,避免二进制处理开销,具有可读性,方便直接修改和处理。写入流程可见下图:
1)所有的写入命令会被追加到 Aof buffer 缓冲区中。
2)AOF 缓冲区根据对应的策略将数据同步到磁盘。
3)随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩对目的。
4)当 Redis 服务器重启时,可以加载 AOF 文件进行数据恢复。
3.2 文件同步策略
Redis 提供三种 AOF 日志写回磁盘策略,由参数 appendfsync 控制,下面对参数有效值逐一介绍:
always 同步写回
命令写入 Aof buffer 后调用系统 fsync 操作同步到 AOF 文件中,fsync 完成后线程可返回。
always 可以做到基本不丢数据,但是在命令执行完后,都会有一个慢速的 fsync 操作,不可避免会影响主线程性能。
优点:可靠性高 缺点:对性能影响较大
everysec 每秒写回
命令写入 Aof buffer 后调用系统 write 操作,write 完成后线程返回。fsync 同步文件操作由专门线程每秒调用一次。
每隔一秒进行一次 AOF 日志刷盘操作,一旦宕机会丢失一秒的数据。是 Redis 默认同步策略。
优点:性能适中 缺点:可能会丢失 1 秒数据 默认选项
no 操作系统控制写回
命令写入 Aof buffer 后调用系统 write 操作,不对 AOF 文件做 fsync 同步,同步磁盘的操作由操作系统负责
通常同步周期最长 30 秒。
每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。
优点:性能高 缺点:宕机会丢失较多数据
3.3 日志重写机制
随着命令不断写入 AOF,文件会越来越大,为了解决这个问题,Redis 引入 AOF 重写机制压缩文件体积。AOF 文件重写是把 Redis 进程内的数据转化为写命令同步到新 AOF 文件的过程。
重写后为什么文件会变小?
1)进程内已超时的数据不再写入文件。
2)旧的 AOF 文件含有无效命令,如 delkey1、hdelkey2、sremkeys、seta111、seta222 等。重写使用进程内数据直接生成,这样新的 AOF 文件只保留最终数据的写入命令。
3)多条写命令可以合并为一个,如:lpush list a、lpush list b、lpush list c 可以转化为:lpush list a b c。
AOF 重写机制降低文件占用空间,更小的 AOF 文件也会被更快的加载。
手动触发
执行下方 bgrewriteaof 命令:
bgrewriteaof
自动触发
根据下方两个参数确定自动触发的时机。
auto-aof-rewrite-min-size:表示运行 AOF 重写时文件的最小大小,默认为 64MB。
auto-aof-rewrite-percentage:当前 AOF 文件大小和上一次重写后 AOF 文件大小的差值,再除以上一次重写后 AOF 文件大小。也就是当前 AOF 文件比上一次重写后 AOF 文件的增量大小,和上一次重写后 AOF文件大小的比值。
3.4 日志重写过程
执行日志重写期间,不会影响主线程正常响应命令。如何实现的呢?
主线程 fork 出后台的 bgrewriteaof 子进程。fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。
因为主线程未阻塞,仍然可以处理新来的操作。此时,如果有写操作,会写入原来的 AOF Buffer 保障此时宕机也可以恢复。当然该操作也会被写入重写日志缓冲区,这样重写日志也不会丢失最新的数据。