持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
AOF
RDB持久化是将进程数据写入文件,而AOF持久化(即Append Only File持久化),则是将Redis执行的每次写命令记录到单独的日志文件中,类似MySQL的binlog;当Redis重启时再次执行AOF文件中的命令来恢复数据。
Redis默认持久化方式
Redis服务器默认开启RDB、关闭AOF;要开启AOF,需要在配置文件中配置:appendonly yes
AOF 执行流程
AOF记录Redis的每条写命令,因此不需要触发。
步骤:
- 命令追加(append):将Redis的写命令追加到缓冲区aof_buf;
- 文件写入(write)和文件同步(sync):根据不同的同步策略将aof_buf中的内容同步到硬盘;
- 文件重写(rewrite):定期重写AOF文件,达到压缩的目的。
1、 追加命令(append)
Redis先将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈。
命令追加的格式是Redis命令请求的协议格式,它是一种纯文本格式,具有兼容性好、可读性强、容易处理、操作简单避免二次开销等优点;具体格式略。在AOF文件中,除了用于指定数据库的select命令(如select 0 为选中0号数据库)是由Redis添加的,其他都是客户端发送来的写命令。
2、文件写入和文件同步
AOF缓存区的同步文件策略由参数appendfsync控制,各个值的含义:
- always:每次有写命令都要同步到AOF文件,硬盘IO成为性能瓶颈,大大降低了Redis的性能;
- no:不实时进行文件同步,同步由操作系统负责,通常同步周期为30秒。文件同步的时间不可控,在一定时间内因为大流量的写入,可能会导致缓冲区中堆积的数据很多,数据安全性无法保证。
- everysec:fsync同步文件操作由独立的线程每秒调用一次。Redis的默认推荐配置
3、AOF文件重写(充分非必要条件,可控制重写或者不重写)
AOF文件过大不仅会影响服务器的正常运行,也会导致出问题后,数据恢复需要的时间过长。所以重写AOF文件的目的是减小AOF文件的体积,缩短数据恢复的时间。
AOF文件重写为啥能减小体积:
(1)数据过期不再写入
(2)重复写入命令,或者key被删除了
(3)多条命令可以合并为一个
4、AOF文件重写的触发方式
(1)手动触发
直接调用bgrewriteaof命令,fork子进程进行,但是在执行fork时会阻塞父进程。
(2)自动触发
根据配置中的2个参数的状态来确定触发时机。
- auto-aof-rewrite-min-size:执行AOF重写时,文件的最小体积,默认值为64MB。
- auto-aof-rewrite-percentage:执行AOF重写时,当前AOF大小(即aof_current_size)和上一次重写时AOF大小(aof_base_size)的比值。
同时满足这两个条件时候,才会自动触发AOF重写,-bgrewriteaof操作。
4、AOF文件重写流程详解
对照上图,文件重写的流程如下:
-
Redis父进程首先判断当前是否存在正在执行 bgsave/bgrewriteaof的子进程,如果存在则bgrewriteaof命令直接返回,如果存在bgsave命令则等bgsave执行完成后再执行。
-
父进程执行fork操作创建子进程,父进程在这个过程中是阻塞的
-
父进程fork后,不再阻塞父进程,并可以响应其他命令。
-
bgrewriteaof执行期间,Redis的写命令双写追加到aof_buf和aof_rewirte_buf两个缓冲区。
-
子进程读取内存快照,按照规则写入到新的AOF文件。
-
子进程写完新的AOF文件后,向父进程发信号,父进程更新统计信息。
-
父进程把AOF重写缓冲区的数据写入到新的AOF文件,这样就保证了新AOF文件所保存的数据库状态和服务器当前状态一致。
-
修改新文件的名称,使用新的AOF文件替换老文件。