更新时间:2022-11-14 来源:黑马程序员 浏览量:
为什么需要AOF 重写?
AOF 会记录每个写命令到 AOF 文件,随着时间越来越长,AOF 文件会变得越来越大。如果不加以控制,会对 Redis 服务器,甚至对操作系统造成影响,而且 AOF 文件越大,数据恢复也越慢。为了解决 AOF 文件体积膨胀的问题,Redis 提供 AOF 文件重写机制来对 AOF 文件进行 “瘦身”。
Redis 通过创建一个新的 AOF 文件来替换现有的 AOF,新旧两个 AOF 文件保存的数据相同,但新 AOF 文件没有了冗余命令。
AOF 重写会阻塞吗?
AOF 重写过程是由后台进程 bgrewriteaof 来完成的。主线程 fork 出后台的 bgrewriteaof 子进程,fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。
所以 AOF 在重写时,在 fork 进程时是会阻塞住主线程的。
AOF 日志何时会重写?
有两个配置项控制 AOF 重写的触发:
auto-aof-rewrite-min-size: 表示运行 AOF 重写时文件的最小大小,默认为 64MB。
auto-aof-rewrite-percentage: 这个值的计算方式是,当前 AOF文件大小和上一次重写后 AOF
文件大小的差值,再除以上一次重写后 AOF 文件大小。也就是当前 AOF 文件比上一次重写后 AOF 文件的增量大小,和上一次重写后 AOF
文件大小的比值。
重写日志时,有新数据写入,主进程是怎么做的?
重写过程总结为:“一个拷贝,两处日志”。在 fork 出子进程时的拷贝,以及在重写时,如果有新数据写入,主线程就会将命令记录到两个 aof 日志内存缓冲区中。如果 AOF 同步策略配置的是 always,则直接将命令写回 旧的日志文件 ,并且保存一份命令至 AOF重写缓冲区 ,这些操作对新的日志文件是不存在影响的。(旧的日志文件:主线程使用的日志文件,新的日志文件:bgrewriteaof 进程使用的日志文件)
而在 bgrewriteaof 子进程完成会日志文件的重写操作后,会提示主线程已经完成重写操作,主线程会将 AOF 重写缓冲中的命令追加到新的日志文件后面。这时候在高并发的情况下,AOF 重写缓冲区积累可能会很大,这样就会造成阻塞,Redis 后来通过 Linux 管道技术让 aof 重写期间就能同时进行回放,这样 aof 重写结束后只需回放少量剩余的数据即可。
最后通过修改文件名的方式,保证文件切换的原子性。
在 AOF 重写日志期间发生宕机的话,因为日志文件还没切换,所以恢复数据时,用的还是旧的日志文件。
在重写日志整个过程时,主线程有哪些地方会被阻塞?
1、fork 子进程时,需要拷贝虚拟页表,会对主线程阻塞 。
2、主进程有 bigkey 写入时,操作系统会创建页面的副本,并拷贝原有的数据,会对主线程阻塞。
3、子进程重写日志完成后,主进程追加 aof 重写缓冲区时可能会对主线程阻塞