1. 什么是 AOF
AOF 是 append only file,AOF 文件中记录了每次的操作指令,在启动 Redis 时,会将 AOF 文件中的数据读取出来以恢复数据。
2. 开启 AOF
Redis 默认关闭 AOF,可以通过将 Redis 配置文件中的 appendonly 设置为 yes,这样就开启了 AOF,此时 RDB 就会关闭,只能使用 AOF 和 RDB 中的一个。
3. AOF 的工作流程
用户执行指令后,会将该指令写入到 AOF 缓冲区(aof_buf,即一段内存缓冲区),当新的指令数量达到一定时,就会将这些新的指令写入到 AOF 文件中,再保存至硬盘。
注意:
- 在向硬盘中写数据时,不是用户执行了一条新指令就写一条,而是将新指令积累到一定数量后统一进行写入,这样可以减少写硬盘的次数,从而降低写硬盘对 Redis 性能的影响。
- Redis 将 AOF 文件写入硬盘是将文件中的数据追加到原文件后,属于顺序读写,速度相对较快。
- 如果在写 AOF 缓冲区时主机突然掉电了,由于数据是存储在硬盘上的,那么这些数据也会消失不见。这就与 Redis 写 AOF 文件的频率有关。
4. AOF 缓冲区同步文件策略
上面我们谈到,当由于有些数据是存储在 AOF 缓冲区的,那么就有可能因为某些原因导致内存上的数据消息,我们可以通过修改缓冲区的刷新策略尽可能地减少上述的问题。
Redis 提供的刷新策略有三种:
- always:只要用户执行了一条指令,就将这条指令写入硬盘;
- everysec: Redis 默认策略,以 1s 为刷新区间,每隔 1s 就将新指令写入硬盘;
- no:操作系统自行刷新缓冲区。
三种刷新策略的比较:
- always:刷新频率最高,数据可靠性最高,但由于涉及到频繁写硬盘,就会降低 Redis 性能;
- everysec: 刷新频率相较于 always 较低,数据可靠性也会降低,但是由于写硬盘的频率降低了,Redis 的性能也会提高;
- no:刷新频率最低,数据可靠性最差,写硬盘的频率最低,Redis 性能最高。
5. AOF 文件重写机制
随着执行的指令数越来越多,那么写入 AOF 文件中的数据也就会越来越多,导致 AOF 文件变得越来越大。由于 Redis 在启动时会将 AOF 中的数据取出,就导致 Redis 的启动时间变长。
- Redis 将AOF 文件进行压缩,将多条指令压缩为一条指令,如:set key1 aaa、set key1 bbb、set key1 ccc,那么就会将这三条指令压缩为 set key1 ccc,以此类推;
- Redis 也会将 AOF 中已经超时的数据删除,以减小文件的大小;
- 删除无效指令,如:del、keys 等。
较小的 AOF 文件会加快 Redis 程序的启动速度,也会减少硬盘的占用。
6. 触发 AOF 重写机制
6.1 手动触发
- 手动执行 bgrewriteaof 指令
6.2 自动触发
- auto-aof-rewrite-min-size:表示触发重写时 AOF 的最小文件大小,默认为 64MB。
- auto-aof-rewrite-percentage:代表当前 AOF 占用大小相比较上次重写时增加比例。
7. AOF 重写流程
- 与 RDB 一样,父进程首先会创建子进程,子进程将指令存入新 AOF 文件中,父进程依然接收客户端请求,子进程进行重写操作;
- 由于在子进程进行重写时,依然会有新的指令依次执行,于是父进程会将新的指令同时写入aof_buf 和 aof_rewrite_buf(也是一段内存缓冲区);
- 当子进程完成复制后,就会给父进程发送信号,父进程就会将 aof_rewrite_buf 中的数据写入到新 AOF 文件中;
- aof_rewrite_buf 中的数据写入完成后,就会将新的 AOF 文件代替旧的 AOF 文件。
注意:
- 子进程在进行重写时,只是将 Redis 中的数据取出来以 AOF 文件的形式存入新 AOF 文件,并不关系指令的操作流程;
- AOF 文件是以文本形式存储数据的,而 RDB 文件是以二进制文件存储数据的,相比之下,读取 RDB 文件中的数据比读取 AOF 文件中的数据速度更快;
- 既然父进程已经将新的指令写入到新的 AOF 文件中,那为什么还要重写旧 AOF 文件?这是因为若在子进程重写的过程中,如果发生主机掉电等问题,由于新 AOF 文件是存储在内存中的,那么新 AOF 文件在主机重启后就会消失,新的指令就不会生效。若将新指令同时写入到旧 AOF 文件中,由于旧 AOF 文件是存储在硬盘上的,那么在 Redis 重启后依然能获取到旧 AOF 文件中的数据,新执行的指令也就会生效,保证了数据完整性。这也就是 AOF 比 RDB 可靠的体现;
- 若在执行 bgrewriteaof 之前就已经有子进程在进行 AOF 重写操作,那么就不会执行此次重写;
- 若在执行 bgrewriteaof 之前已经有子进程在进行 RDB 重写操作,那么会等待 RDB 重写执行完再执行 AOF 重写操作。
8. 混合持久化
由于 AOF 文件中的数据是以文本形式存储的,那么在启动 Redis 时读取 AOF 文件中的内容所消耗的时间就会变多,于是可以采取使用 RDB 文件存储方式,即使用二进制存储数据,那么就会加快文件的读取速度。
在 Redis 的配置文件中,若将 aof_use_rdb_preamble 设置为 yes,就表示以二进制形式存储数据。Redis 默认 aof_use_rdb_preamble 为 yes。