本篇重点谈一谈自己对AOF重写的理解,不讲代码!不讲代码!!不讲代码!!!
因为redis是内存型的nosql数据库,所以对于数据的安全问题必须要考虑,redis支持将数据持久化的磁盘。redis的持久化方式有两种——RDB和AOF。
对于RDB,简单提一句,通俗的说它就是一个快照(备份)机制,在某时刻redis会产生一个父进程的副本(快照),并由子进程将快照写入临时文件,这种方式看起来非常简单粗暴,而且可以想象,如果系统发生崩溃,且在最近一次rdb之后还有未备份的数据,那么这些数据会损失掉,我们大多数情况下是不能接受这样的数据损失的(比如电商系统),所以RDB的这种机制并不适于实时性的持久化。
AOF是redis的另一种持久化的机制,相对于RDB,redis就更适合于更实时的数据持久化操作。
那么AOF是通过怎样的机制进行数据的持久化呢?
首先redis会将其运行过程中执行成功的每一个写操作(操作指令),写入一个.aof文件,当redis重启时,只需要完全的执行一次已经保存的aof文件,就可以恢复以前的数据。由于保存的是操作指令,通过将aof文件复制到其他服务器执行,就可以实现数据的移植。由于aof存放的是操作指令,所以它单次的消耗会远低于RDB,所以它更适合做更实时的持久化。
需要注意的是,如果RDB和AOF同时存在,那么redis会以AOF为准。
AOF中有怎样的配置用来控制AOF的写入频率呢?
AOF有这样几种配置用来控制读写的频率:
(1)每次一收到写命令就立即强制写入磁盘,保证完全的持久化。(对应配置 appendfsync always)
这种做法看起来几乎完美无缺,最大程度上的实现了数据的完整性,但是我们忽略了redis的读写效率。通过在redis目录下执行redis-benchmark命令可以查看redis的读写效率,大概在10w次/s,这样的一个超高速度对于我们的磁盘来说几乎是不可承受的,如果某一时刻redis的写操作达到这样的峰值,我们的磁盘大概会崩溃,这样的机制在一个心脏大血管小的场景下,会极大的产生io开销,其实很难保证数据的安全。
(2)由操作系统决定何时同步数据。(对应配置 appendfsync no)
这样的机制就更不用说了,我们完全没办法确定操作系统的选择,虽然这种操作保证了性能,但是如果系统宕机,那么redis会丢失多少数据也是我们不能确定的。
(3)每秒钟强制写入磁盘一次。(对应配置 appendfsync everysec)
这种机制在性能和持久化方面做了很好的折中,虽然一秒钟的时间在我们看起来很短,但是对于redis确是很长的一段时间,毕竟人家10w次的读写效率在那里摆着。而这种机制也是redis推荐的配置,打开redis的配置文件就会发现,前面两种配置都是被注释掉的。
AOF在开启过程中有什么需要注意或者了解的?
首先,AOF的同步时间间隔很小,能使得数据更安全,理论上来说,在AOF状态下redis至多丢失一秒的数据,因为我们的推荐配置就是每秒钟强制写入一次,它比RDB的实时性更高。其次,当redis重启时,可能会执行一个非常大的aof,因为我们所有数据的写操作可能都被保存在.aof文件中,这样的话会导致redis重启时间很长(大数据中是以100G数据为入门级别的)。而第三点,就是AOF文件会不断的增长,它可能会比RDB产生的快照文件大几倍,因为它保存的是对所有数据的所有写操作,而我们通常对同一数据不止进行一次写操作,或增加或修改或删除,同一数据可能会有很多这样的操作,数据量小的情况下或许没什么,但是在极端情况下,就可能会对磁盘空间造成压力。
那么如何解决AOF文件增长的问题呢?就引出了本篇随笔的重点——AOF重写。
AOF重写的实现
为了减小aof文件的体量,可以手动发送“bgrewriteaof”指令,通过子进程生成更小体积的aof,然后替换掉旧的、大体量的aof文件。
AOF重写的工作原理
上图就是AOF的工作原理了,感觉自己画的还是比较通俗易懂的哈哈哈
需要注意的是,在这里子进程把数据转为写指令存入新的AOF文件时,记录的只是每个数据的最后一次写指令,也就是最新的数据,不会记录之前冗余的操作,所以这样会很大程度的缩小AOF的体量,同时,该操作是产生新的AOF文件进行写入,而不是在原有文件上的修改,通过上图也可以看出来。而缓存中叠加到新的aof的操作仍是新增的全部操作,但是这些数据已经很有限,相比之前的一股脑添加,这种机制很好的解决的AOF文件不断增大的问题。
AOF重写的相关配置
1)auto-aof-rewrite-percentage 100
2)auto-aof-rewrite-min-size 64mb
这两个配置项的意思是,在aof文件体量超过64mb,且比上次重写后的体量增加了100%时自动触发重写。我们可以修改这些参数达到自己的实际要求
AOF重写须知
和RDB一样,如果当前的数据量巨大,那么创建子进程的过程会很耗时。在大数据的处理工作中,文件的删除也是一项比较麻烦的工作。想我们普通的笔记本电脑,删除一个几GB的文件都是一项很耗时的工作,更何况大数据的量级远远大过我们日常使用的数据。所以在替换aof文件时,如果旧的aof很大,删除它也是一个很耗时的过程。当然这并不是aof或者redis的缺点,只是可能会出现的一个客观情况。