AOF持久化机制:
AOF(Append Of File):将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些指令从前到后重复执行一遍,就可以实现数据恢复了。
以独立日志的方式记录每次写命令,重启时候重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了持久化的实时性。
开启方式:
开启AOF功能需要设置配置:appendonly yes ,默认不开启。
AOF文件名通过appendfilename配置设置,默认文件名是appendonly.aof
保存AOF文件的路径和RDB持久化一致,通过dir配置指定。
AOF持久化不断优化的过程:【先看这个流程!!】
大家都知道,redis也是基于命令式的,每天的工作就是响应业务程序员发来的命令请求,学着mysql的样子,把执行的所有写入命令都记录下来,专门写入了一个文件,并给这种持久化的方式取了一个名字,叫做AOF。
但是现在应该多久写一次文件呢?肯定不能每执行一条写入命令就记录到文件中,那会严重拖垮redis的性能。所有就有一个缓冲区,然后把要记录的命令先临时保存在这里,然后再找时机写入文件,这个临时的缓冲区就叫做aof_buf。但是随着时间的推移,这个AOF的备份文件越来越大,不仅非常占用硬盘的空间,就连加载的时候也非常耗时。
那就得想办法将文件给压缩一下,这个过程就叫做AOF重写,如果瘦身的途径是去除冗余,那样的工作量实在是太大了。原来记录一条条指令的方式太笨了,数据改来改去,有很多中间状态都没有用,直接把最终的数据状态记录下来就好了,和RDB的方式一样,fork出一个子进程来做这件事。
!子进程再重写期间,我要是修改了数据,就会出现和重写的内容不一致的问题,需要把这个漏洞给补上,所以就出现了AOF重写缓冲区 aof_rewrite_buf,从创建重写子进程的那一刻起,就把后面来的写入命令也copy一份写到这个从写缓冲区中,等到子进程重写文件结束之后,再把这个重写缓冲区中的命令写入到aof的文件中,最后再重命名新的文件,替换掉原来的文件。
AOF写入策略和AOF同步策略:
写入策略:
写入策略主要是讲如何将数据写入到AOF文件中。主要是通过“write”系统调用来实现的。写入策略决定了Reids在执行写操作时,如何将这些操作记录追加到AOF文件中。
同步策略:
同步策略说的是何时从缓存中同步到物理磁盘。主要是通过“fsync”系统调用来实现的。同步策略决定了Redis何时调用“fsync”来确保数据持久化到硬盘。
同步策略的三种模式:
redis提供了几种不同的AOF同步策略,通过配置“appendfsync”选项来控制“write”和“fsync”调用的频率
【appendfsync 配置在redis.window.conf文件中】
1、always:每次写操作以后就立即调用“fsync”
2、everysec(这个是默认配置的):每秒调用一次“fsync“
3、no:不主动调用”fsync“,让操作系统自己决定何时将数据从页缓存写入磁盘
AOF写入和同步过程中的内核页缓存:
1、写入过程(write系统调用):
当redis将'aof_buf'的数据通过'write'系统调用写入到AOF文件中是,这些数据会先进入操作系统的内核页缓存。此时数据还没有实际写入磁盘。
2、同步过程(fsync系统调用):
根据AOF同步策略(’always‘、’everysec‘、’no‘),reids会调用’fsync‘系统调用,将内核缓存中的数据写入到磁盘。’fsync‘确保数据从内核页缓存写入到物理磁盘,实现持久化。
具体流程:
1、当执行一个写操作(SET key value)的时候,写操作的命令会被记录。
2、写操作命令被追加到Redis内部的'aof_buf'缓冲区中。
3、Redis通过'write'系统调用将‘aof_buf’中的数据写入到AOF文件。
数据此时被写入操作系统的内核页缓存,而不是立即写入磁盘
4、数据暂时存储在操作系统的内核页缓存中,此时数据还未持久化到磁盘。
5、根据AOF同步的策略,Redis会在合适的时机(例如每秒一次或者每次的写操作后)调用'fsync'系统调用。
’fysnc‘确保内核页缓存中的数据被写强制写入到磁盘中。
6、最终,数据从内核页缓存被写入到物理磁盘,确保数据持久化。
AOF重写流程:
1、执行AOF重写请求,如果当前进程在执行AOF重写,请求不执行并返回如下响应:{ ERR Background append only file rewriting already in progress }
如果当前进程正在执行bgsave操作,重写命令延迟到bgsave完成之后在执行,返回如下的响应:{ Background append only file rewriting scheduled }
2、父进程执行frok创建子进程,开销等同于bgsave过程。
3、主进程fork操作完成后,继续响应其他命令。所有修改命令依然写入AOF缓冲区并根据appendfsync策略同步到硬盘,保证原有AOF机制的正确性。
由于fork操作运用写时复制技术,子进程只能共享fork操作时的内部数据。由于父进程依然相应名命令,Redis使用“AOF重写缓冲区”保存这部分新数据,防止新AOF文件生成期间丢失这部分数据。
4、子进程根据内存快照,按照命令合并规则写入到新的AOF文件。每次批量写入硬盘的数据量由配置aof-rewrite-incremental-fsync控制,默认为32MB,防止单次刷盘数据过多造成硬盘阻塞。
5、新的AOF文件写入完成后,子进程发送信号给父进程,父进程更新统计信息,具体见info persistence 下的aof_* 相关统计父进程把AOF重写缓冲区的数据写入到新的AOF文件使用新AOF文件替换老文件,完成AOF重写。
总结一下流程:
1、父进程启动重写操作
2、父进程通过' fork ' 创建子进程
3、子进程在独立的缓冲区中重写AOF文件
4、子进程重写完后通知父进程
5、父进程合并增量数据并替换旧的AOF文件
AOF的优缺点:
AOF的优点:
数据保证:我们可以设置fsync策略,一般默认是Every,也可以设置每次写入追加,所以即使服务死掉了,也最多丢失一秒数据。
自动缩小:当AOF文件大小到达一定程度的时候,后台自动的去执行AOF重写,此过程不会影响主进程,重写完成后,新的写入将会写到新的AOF中,旧的就会被删除掉。但是此条如果拿出来对比RDB的话还是没有必要算成优点,只是官网显示成优点而已。
AOF的缺点:
性能相对较差:它的操作模式决定了他会对Redis的性能有所损耗。(主线程写文档)
体积相对更大:尽管是将AOF文件重写了,但是毕竟是操作过程和操作结果仍然由很大的区别,体积也毋庸置疑的更大。
恢复速度更慢:因为要重新加载每条命令的执行,恢复速度比较慢。