通过设置配置项appendonly yes即可开启AOF持久化,默认不开启
AOF的工作流程:命令写入aof buffer-->同步到文件-->文件重写-->启动时加载AOF文件。如下图
可以通过参数appendfsync参数来控制缓冲区同步文件策略,参数及其说明如下表
可配置值 | 说明 |
always | 每次命令写入aof_buffer后都会调用fsync同步到aof文件,fsync完成后线程才返回。线程每次都会等fsync完成后才返回,性能较差,数据安全性最高 |
everysec | 命令先写入aof_buffer,然后调用系统write操作,write操作完成后线程就返回,由后台专门的线程每秒执行一次fsync操作。推荐使用;最多丢失2s内的数据,之后会解释为什么是2s。 |
no | m命令先写入到aof_buffer,然后调用系统write操作,write操作后线程返回,fsync操作由操作系统负责,时间不确定。fsync由系统负责,数据安全性无法确保,并且会加大每次fsync同步到硬盘的数据量。不推荐 |
AOF重写:
随着命令的不断写入,会导致aof文件越来越大,这样肯定是不行的,所以需要重写AOF文件,来使AOF文件变小,同时redis从更小的aof文件中恢复数据也更快。
为什么重写可以使AOF文件变小呢?
1、aof文件中存储了大量无用的命令,例如del key1,set key2 A、set key2 B,aof文件中有些命令完全是无效或者多余的;所以redis重写时会根据线程内存中的数据重新生成有效的命令
2、AOF中包含了过期的数据的命令
3、把多条命令合并,例如lpush list A、lpush list B可以转化成lpush list A B;同时为了防止单挑命令过大造成客户端缓冲区溢出,会以64个元素为界限拆分成多条命令
如何触发AOF重写呢?
1、手动触发:使用命令bgrewriteaof
2、自动触发:redis根据参数auto-aof-rewrite-min-size和auto-aof-rewrite-percentage自动确定触发时机
auto-aof-rewrite-min-size:代表触发aof重写的最小文件体积,默认64M
auto-aof-rewrite-percentage:代表当前aof文件空间(aof_current_size)和上一次重写后aof文件空间(aof_base_size)的比值,用来确定aof文件增长多少后触发重写
自动触发的机制:aof_current_size > auto-aof-rewrite-min-size && (aof_current_size - aof_base_size) / aof_base_size >= auto-aof-rewrite-percentage
AOF重写流程:
流程说明:
(1)如果当前正在执行AOF重写,则请求不执行;如果当前正在执行bgsave,则重写延迟到bgsave操作完成后执行
(2)主进程fork出子进程,会短暂阻塞主进程影响读写
(3.1)fork完成后,主进程继续响应命令,并把修改命令写入到aof_buf,并根据appendfsync策略同步到磁盘,保证原有AOF机制的正确性
(3.2)由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据,且由于主进程依然响应命令,所以需要把重写期间的命令保存到“AOF重写缓冲区(aof_rewrite_buf)“,防止新生成的aof文件丢失重写期间的数据
(4)子线程根据共享的内存快照,根据命令合并规则生成新的aof文件。每次批量写入磁盘数据量由aof-rewrite-incremental-fsync控制,默认32M,防止单次刷盘数据过多造成磁盘阻塞
(5.1)新的aof文件写入完成后,子进程发送信号给父进程,父进程更新统计信息
(5.2)主进程把AOF重写缓冲区的数据写入到新的aof文件
(5.3)新的aof文件替换旧的aof文件
重启加载备份文件:
如下图
关于AOF追加阻塞:
当使用everysec同步硬盘策略时,redis会由专门的子线程负责对aof_buf中的数据执行fsync操作同步到硬盘,当硬盘资源紧张时会造成redis主线程阻塞。
阻塞流程:
1、主线程把数据写入到aof_buf
2、子线程每秒执行一次fsync操作
3、主线程把数据写入到aof_buf后会对比上次fsync操作的时间,此时有有两种情况:①如果距上次fsync操作成功时间大于2s则阻塞主线程直到fsync操作完成。②如果距上次fsync操作成功时间小于2s则主线程直接返回。
所以,1、everysec配置项最多丢失2s的数据,而不是1s。2、如果fsync操作慢的话可能会造成redis主线程阻塞,影响吞吐量。
以上内容来自阅读《Redis开发与运维》后的总结与笔记