AOF日志
定义:redis每执行一条命令,就将该命令已追加的方式写入到一个文件里,然后重启redis的时候,先去读取这个文件里的命令,并且执行它,就可以实现redis持久化。这种保存写操作命令到日志的持久化方式是redis里面的AOF持久化功能。

注意:
redis是先执行操作命令后将命令记录到AOF日志。
两个好处:
1.避免额外的开销,当该命令有错误时,进行语法检查,就不会将错误命令记录到日志。
2.不会阻塞当前写操作命令的执行,因为当写操作执行成功后才会执行记录到AOF日志。
AOF文件中 *3 代表当前命令有三个部分,每部分都是以$+数字开头,数字代表每个命令的字符串长度。
三种写回策略
redis写入AOF日志的过程:

我们来解释一下上图操作:
1.redis执行写操作命令,会将命令加入aof_buf缓冲区。
2.write系统调用后,将缓冲区的数据写入到aof文件,此时并没有写入磁盘。
3.具体什么时候i写入磁盘有内核决定。
1.每次操作都写入日志
1.Always,这个单词的意思是总是,所以他的意思是每次写操作命令执行完后,同步将AOF日志数据写会硬盘。
2.每秒写入日志
2.Everysec,每次写操作命令执行完后,先将命令写入到+AOF+文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写回到硬盘。
3.操作系统控制写回机制
3.No,意味着不由+Redis+控制写回硬盘的时机,转交给操作系统控制写回的时机,也就是每次写操作命令执行完后,先将命令写入到+AOF+文件的内核缓冲区,再由操作系统决定何时将缓冲区内容写回硬盘。

AOF重写机制
AOF日志是一个文件,如果文件过大就会带来性能问题,Redis为了避免AOF文件越写越大,提供了重写机制,来压缩AOF文件。
AOF重写机制是在文件重写时,读取当前数据库中的所有键值对,然后将每一个键值对用一条·命令记录到新的AOF文件,等全部记录完成后,然后将新的AOF文件替换掉旧的AOF文件。

AOF后台重写
写入AOF日志的操作虽然是在主进程中完成的,是因为他写入的内容不多,所以一般不太影响命令的操作。但是在触发AOF重写机制时这个过程是很耗时的,所以1redis的重写机制是由后台子进程来完成的。
两个好处:
子进程进行AOF重写期间,主进程可以继续处理命令请求,从而避免阻塞主进程。
子进程带有主进程的数据副本。
为什么使用进程而不使用进程?
多线程之间会共享数据,共享内存,那么在修改共享数据的时候需要加锁保证数据安全,从而降低性能。
子进程重写期间会有两个过程导致主进程阻塞:
创建子进程途中,由于要复制父进程的页表等数据结构,阻塞的时间跟页表的大小有关,页表越大,阻塞的时间越长。
创建子进程后,如果子进程或父进程修改了共享数据,就会发生写时复制,注意这里只会复制主进程修改的物理内存数据,没修改的还是与子进程共享。
子进程在重写时,主进程仍然可以正常处理命令。如果此时主进程对已经存在的key_value键值对进行修改,此时这个key_value数据在子进程的内存数据就跟主进程不一样了,为了解决这种数据不一致的问题,redis设置了一个AOF重写缓冲区。
再重写AOF文件期间,redis执行的命令都会保存在AOF缓冲区和·AOF重写缓冲区。

三个工作:
执行客户端发下来的命令·。
将执行后的写命令追加到AOF缓冲区。
将执行后的写命令追加到AOF重写缓冲区。
当子进程完成重写工作后,回向主进程发送一条信号,信号是通信间的一种方式,且是异步的。
主进程收到信号后,会调用信号处理函数,该函数主要做以下工作:
将AOF重写缓冲区中的所有内容加到新的AOF文件里。
新的AOF文件覆盖掉现有的AOF文件。
AOF总结
AOF日志:当redis每执行一条命令,就将其写入到aof_buf缓冲区,通过三种写回策略将缓冲区内容写入到AOF文件,当AOF文件过大时,通过AOF后台重写机制,压缩体积。
RDB快照
定义:RDB快照就是记录某一瞬间的内存数据,记录的是实际数据即二进制数据。因此在redis恢复数据时采用RDB会比AOF高一些,因为直接将RDB文件读入内存就可以了。
快照怎么用?
redis提供了两种方式来生成RDB文件,分别是save和bgsave,他们的主要区别在于是否在主线程中执行:
执行了save命令就会在主线程中生成RDB文件,可能会阻塞主线程。
执行了bgsave命令后,会创建一个子进程来生成RDB文件,这样可以避免主线程的阻塞。
RDB文件加载是在服务器启动时自动执行。
Redis 还可以通过配置文件的选项来实现每隔一段时间自动执行一次 bgsave 命令,通常可能设置至少 5 分钟才保存一次快照,这时如果 Redis 出现宕机等情况,则意味着最多可能丢失 5 分钟数据。
执行快照时,数据能被修改吗?
执行 bgsave 过程中,Redis 依然可以继续处理操作命令的,也就是数据是能被修改的。
那具体如何做到到呢?关键的技术就在于写时复制技术。
创建子进程时:

修改共享数据后:

如果主线程(父进程)要修改共享数据里的某一块数据(比如键值对 A)时,就会发生写时复制,于是这块数据的物理内存就会被复制一份(键值对 A'),然后主线程在这个数据副本(键值对 A')进行修改操作。与此同时,bgsave 子进程可以继续把原来的数据(键值对 A)写入到 RDB 文件。
RDB与AOF合体
尽管 RDB 比 AOF 的数据恢复速度快,但是快照的频率不好把握:
- 如果频率太低,两次快照间一旦服务器发生宕机,就可能会比较多的数据丢失;
- 如果频率太高,频繁写入磁盘和创建子进程会带来额外的性能开销。
RDB与AOF合体混合使用 AOF 日志和内存快照,也叫混合持久化。混合持久化工作在 AOF 日志重写过程。
如果想要开启混合持久化功能,可以在 Redis 配置文件将下面这个配置项设置成 yes:
aof-use-rdb-preamble yes
当开启了混合持久化时,在 AOF 重写日志时,fork 出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件,然后主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以 AOF 方式写入到 AOF 文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。
