AOF
什么是AOF:
Redis在执行完成一条写命令后,将命令以追加的方式持久化到硬盘的日志文件中,这个日志就叫做AOF日志
AOF写入流程:
-
在执行完命令后,将命令写入到AOF_BUF文件中
-
通过执行write系统调用,将AOF_BUF文件的数据写入到AOF文件中,注意这里还没有写入到硬盘,只是写入到了系统缓冲区中
-
这里Redis提供了3中策略来将系统缓冲区的内容写入到磁盘中,也就是控制何时执行fsysc()函数
-
Always: 每次执行命令后都将数据写入到磁盘
-
EverySec: 每秒将数据写入到磁盘
-
NO: Redis不主动执行,由操作系统决定何时将数据写入到磁盘
-
AOF重写:
Redis为了避免AOF文件越写越大,在每隔一段时间,Redis会进行AOF重写:Redis将内存的每一个键值用一条命令存储到新的AOF文件中,等所有键值都存储完成后,就用新的AOF文件替换掉旧的AOF文件。
AOF后台重写:
AOF重写是比较耗时的,为了不阻塞主进程,需要一个子进程来执行AOF重写
操作系统将主进程的页表
复制一份给子进程,这样主进程和子进程就共用一块内存,这块内存是只读的,当主进程要写入数据时,操作系统就会将数据复制一份,并更改主进程的页表
映射,主进程就修改复制后的数据,不会影响到子进程的AOF重写,这个操作叫做写时复制(Copy On Write)
所以AOF重写期间,只有2个阶段会阻塞主进程:
- 复制主进程的页表数据,如果页表较大,会比较耗时
- 主进程修改了共享数据,发生
写时复制
,如果复制的数据较大,会比较耗时
在AOF重写期间,主进程任然在处理命令,主进程执行的写命令会被记录到AOF重写缓冲区
,当子进程重写完成后,主进程会将AOF重写缓冲区
追加到新的AOF文件中,然后用新的AOF文件替换掉旧的AOF文件
所以AOF重写期间,主进程需要执行3个工作:
- 执行客户端发来的命令
- 将命令追加到
AOF缓冲区
- 将命令追加到
AOF重写缓冲区
RDB
什么是RDB:
RDB是Redis的全量持久化技术,它用于记录某一刻的Redis数据的全量快照,使用save
(主进程执行)或者bgsave
(后台进程执行)可以记录RDB快照,因为是全量,它的执行效率比AOF低,但它恢复数据的效率比AOF高。
RDB快照是怎么后台执行的
和AOF重写类似,使用的也是写时复制技术(Copy On Write)
。父进程会通过fork()
创建子进程,父进程把页表
复制给了子进程,父子进程共享同一块内存。子进程负责创建RDB快照,主进程依然可以接收命令,如果主进程想要修改某一块共享数据,需要先复制这块数据,然后再进行修改。RDB保存的是开始执行RDB快照那一刻的数据,对于RDB执行期间的数据不会被保存。
RDB和AOF混合持久化
当开启了混合持久化后,会改变AOF重写日志的方式。在AOF重写日志时,子进程将以RDB方式写入AOF文件,而不是以AOF方式写入AOF日志,写完之后在将AOF重写日志追加到AOF文件中。也就是说,最终的AOF文件的前半部分是RDB格式的全量数据,后半部分是AOF格式的增量数据。这样的话,AOF重写既有较高的性能(RDB全量快照),也有较好的数据安全(重写期间的数据使用AOF增量日志)
大Key 对持久化的影响
在AOF重写和RDB快照过程中,有两个阶段会阻塞主进程:
- 在创建子进程时,主进程会复制页表给子进程,如果存在大Key,页表也会比较大,复制的时间也会更长。
- 在写时复制时,当主进程想要修改共享内存中的某一个大Key,会先复制这个大Key,因为大Key的内存占用较大,复制这一过程也会比较耗时
RDB和AOF的效率
RDB文件内容是经过压缩的二进制数据(不同数据类型数据做了针对性优化),文件很小。而AOF文件记录的是每一次写操作的命令,写操作越多文件会变得很大,其中还包括很多对同一个key的多次冗余操作。在主从全量数据同步时,传输RDB文件可以尽量降低对主库机器网络带宽的消耗,从库在加载RDB文件时,一是文件小,读取整个文件的速度会很快,二是因为RDB文件存储的都是二进制数据,从库直接按照RDB协议解析还原数据即可,速度会非常快,而AOF需要依次重放每个写命令,这个过程会经历冗长的处理逻辑,恢复速度相比RDB会慢得多,所以使用RDB进行主从全量复制的成本最低。