参考:
小林coding https://xiaolincoding.com/redis/storage/aof.html#aof-%E9%87%8D%E5%86%99%E6%9C%BA%E5%88%B6
https://www.cnblogs.com/lovezhr/p/15886823.html
AOF(Append Only File)
如果 Redis 每执行一条写操作(不会记录读操作命令)命令,就把该命令 以追加的方式写入到一个文件里,然后重启 Redis 的时候,先去读取这个文件里的命令,并且执行它,以此来恢复数据。
AOF 日志文件其实就是普通的文本,我们可以通过 cat
命令查看里面的内容,有着一定的格式
不知道大家注意到没有,Redis 是先执行写操作命令后,才将该命令记录到 AOF 日志里的,这么做其实有两个好处。
- 第一个好处,避免额外的检查开销。如果先执行写操作命令再记录日志的话,只有在该命令执行成功后,才将命令记录到 AOF 日志里,这样就不用额外的检查开销,保证记录在 AOF 日志里的命令都是可执行并且正确的。
- 第二个好处,不会阻塞当前写操作 命令的执行,因为当写操作命令执行成功后,才会将命令记录到 AOF 日志。
当然,AOF 持久化功能也不是没有潜在风险。
- 第一个风险,执行写操作命令和记录日志是两个过程,那当 Redis 在还没来得及将命令写入到硬盘时,服务器发生宕机了,这个数据就会有丢失的风险。
- 第二个风险,前面说道,由于写操作命令执行成功后才记录到 AOF 日志,所以不会阻塞当前写操作命令的执行,但是可能 会给「下一个」命令带来阻塞风险。因为将命令写入到日志的这个操作也是在主进程完成的(执行命令也是在主进程),也就是说这两个操作是同步的。
三种写回策略
和 mysql redo log 的 AOF 策略类似,将文件写到硬盘,需要两次系统调用:
- redis 在用户态中将命令追加到程序的
server.aof_buf
缓冲区; - 第一次系统调用是 write() 写到操作系统的文件缓存 pageCache
- 第二次系统调用是 fsync() 将 pageCache 的文件缓存正式写到硬盘
- redis 在用户态中将命令追加到程序的
Redis 提供了 3 种写回硬盘的策略,控制的就是上面说的第三步的过程。
-
- Always 策略就是每次 write() 写入 AOF 文件数据到 pageCache 后,就立即执行 fsync() 函数;
- Everysec 策略就会创建一个异步任务来执行 fsync() 函数;
- No 策略就是永不执行 fsync() 函数,由操作系统自己来控制写回时机;