在redis运行期间,不断将redis执行的写命令写到文件中,redis重启之后,只要将这些命令重复执行一遍就可以恢复数据。因为AOF只是将少量的写命令写入AOF文件中,因此其执行效率高于RDB,开启AOF即使Redis发生故障,丢失的数据也较少。
appendonly yes
appendfilename appendonly.aof
aof重写:随着命令不断添加aof文件会越来越大,redis会进行aof的重写,每个健只会写入最后一次命令,已删除或过期的数据相关命令将抹去。
- AOF定时逻辑
- 判断是否存在AOF重写操作,若当前没有子进程则执行AOF重写操作
- AOF重写条件
- AOF文件大于server.aof_rewrite_min_size
- 上次AOF重写后的文件大小,当前AOF文件增加的空间大小比例已经超过了server.aof_rewrite_perc配置,此配置默认为100.例如上次重写aof大小为80MB,现在aof文件有160了,则满足重写要求。
- 存在延迟的AOF缓冲区刷新操作,则将数据从缓冲区刷到文件中。
- 每经过一段时间,执行:若上次AOF缓冲区刷新操作中写入磁盘出错,则再次刷新缓冲区
- AOF持久化过程
- 命令传播
- 对带EXPIRE、EXPIREAT、PEXPIRE、SETEX、PSETEX,或者带EX、PX选项的SET命令做特殊处理。因为这些命令带有过期时间,需要将这些命令转换为PEXPIREAT命令,将过期时间的时间戳写入buf暂存区。
- 对于其他命令将命令写入buf暂存区
- 若服务器开启AOF功能,则将buf暂存区内容写入AOF缓冲区
- 如果当前线程正在执行AOF重写操作,则还需将buf暂存区内容写入到AOF重写缓冲区
- 刷新AOF缓冲区
- 当AOF缓冲区为空时,如果刷盘策略为每秒同步,且当前存在待同步的数据,距上次同步已经过去一秒,则开始同步。否则退出。
- 检查后台线程是否正在执行同步操作,若存在则执行以下逻辑:若同步策略为每秒同步,则延迟AOF缓冲区刷新操作。如果已经延迟多次且延迟时间超过2秒,则强制刷新AOF缓冲区。
- 将AOF缓冲区内容写入文件
- aof缓冲区内容刷新成功后,若aof总空间小于4kb,则清空并重用aof缓冲区,否则新建一个新的缓冲区。
- 同步磁盘
- 刷盘策略:
- 不执行fsync,速度快的安全性低
- 执行fsync,安全性高速度慢
- 每个一秒执行fsync,折中处理
- 如果程序存在子进程,且开了server.aof_no_fsync_on_rewrite配置,就不同步磁盘
- 若刷盘策略是每次同步(2),则开始同步磁盘
- 若刷盘策略为每秒同步,且距上次同步已经过去一秒,则添加一个后台任务同步磁盘
- 刷盘策略:
- 命令传播
- AOF重写
- aof混合持久化
- 若开启混合持久化,在AOF重写时,会将redis数据以RDB格式保存到新文件中,再将重写缓冲区增量写命令以aof格式写入文件。
- 重写过程:
- fork一个子进程(aof进程),负责将当前内存数据保存到一个新文件中
- 打开一个临时文件并初始化rio变量
- 若开启了aof持久化,则生成rdb文件到临时文件中,否则将redis数据转化为写入命令写入临时文件
- 重复从server.aof_pipe_read_data_from_parent读取增量命令:
- 读取时间超过一秒或者连续20毫秒没有读取到则停止
- 若没有读取到增量命令则阻塞一秒等待增量命令
- 通知主进程(父进程)停止发送增量命令
- 再一次从server.aof_pipe_read_data_from_parent读取增量命令
- 将暂存区内容写入文件并同步磁盘
- 重命名文件
- 将步骤一执行期间的增量命令写入新文件中
- 主进程收尾,将步骤二执行期间主进程执行的赠礼命令写入新文件中,替换新的AOF文件
- 打开aof进程创建的文件
- 将重写缓冲区内容写入临时文件
- 重命名文件进行替换
- 磁盘同步并清空server.aof_buf内容
- fork一个子进程(aof进程),负责将当前内存数据保存到一个新文件中
- aof混合持久化
- AOF文件加载:
- 打卡aof文件
- 创建一个伪客户端,执行aof文件中的命令
- 如果文件以redis标志开头,则该aof文件是混合持久化方式生成,需调用处理RDB内容的函数加载RDB内容
- 处理aof文件中的命令
- 按照RESP协议格式,读取命令参数数量
- 读取每一个参数
- 查找命令redisCommand
- 调用redisCommand.proc执行命令