redis aof写入以及aof重写的源码分析

版本

redis:6.2.7

aof的面试问题

最近找工作,面试被问倒了,记录一下
比如redis的aof指令会不会丢失?比如在重写aof的什么新来的操作怎么办?

在重写的时候会新开一个文件,这个大家可能都知道,然后会将新来的操作放在重写缓冲区,但是这个要不要落地,怎么落地?难住我了。后面想了想应该是写入老的aof文件,重写缓冲区内存存一份,当老的aof文件重写完成后,父进程上锁阻塞重写缓冲区,让新的aof写入新接收的指令,再解锁重新接收指令,这样避免了数据丢失,同时也最低限度避免了阻塞耗时,但是我觉得这样加锁性能会有蛮大的损耗,但也想不出来其他好的做法,当然这个只是我面完试之后一个说的通的猜想。注:这是错误的猜想,单纯记录当时的想法,具体过程还是给看代码梳理流程

aof正常写入流程

aof是写后日志,肯定是在执行完redis命令之后写入的。feedAppendOnlyFile核心函数,每当执行call函数之后,执行完相应的cmd就会调用propagate函数,随后就调用feedAppendOnlyFile,一般来说应该是在指令执行完的beforeSleep调用flushAppendOnlyFile,进行相应的程序缓冲区写入、内核缓冲区flush以及fsync到硬盘中。

feedAppendOnlyFile函数只会单纯记录aof_buf,不涉及操作系统write操作,同时如果有一个子进程打开类型还是aof重写的,会加入到重写缓冲区aof_rewrite_buf_blocks这个字段里,数据结构是双向链表
在这里插入图片描述
flushAppendOnlyFile函数会涉及write、flush、fsync操作,正常写入流程还是比较简单易懂的

aof重写流程

这一块的流程比较复杂。
核心函数rewriteAppendOnlyFileBackground,在每次重写的时候都会先创建一组管道,下标0是读管道,下标1是写管道,依次类推,看成2个一组就好了。
在这里插入图片描述
然后会进入rewriteAppendOnlyFile,这个是重写的核心函数,子进程copy on write临时文件之后,会有一个简单读父进程发来aof的buf的过程,两个维度来进行控制
在这里插入图片描述
然后就是发信号通知父进程不要在发差异(就是重写缓冲区数据)了,子进程要读完已发过来的差异就准备rename文件去了,这个rename的是temp-rewriteaof-%d.aof这个文件,名字要变成temp-rewriteaof-bg-%d.aof,%d指的是子进程id。
在这里插入图片描述
这个时候我一直在思考,子进程已经不让父进程继续同步了,再来新的指令怎么存到新aof文件啊?子进程马上就要退出了呀,父进程可以把新来的命令存到老的aof文件中,那新的aof文件怎么获取新的命令?父进程又不会重新处理新的aof文件,再三确认没有阻塞机制,我就在猜想那一定会丢相应的aof记录啊,但一想这么牛逼的产品怎么可能会在重写文件上丢失命令,自己重新编了编测了测,发现并没有丢失,觉得很神奇,为什么不阻塞,新aof文件还是对的,百思不得其解。上网也查了查发现页没有相关解答,又看了看redis debug 日志,顺着日志走找到解决思路。

serverCron函数中,有这样的一个操作,会检查子进程是否操作完。不同类型的处理函数也是不同的,backgroundRewriteDoneHandler这个函数是主角,在checkChildrenDone
在这里插入图片描述
子进程fork重写完成,父进程还没有清理相应子进程状态,父进程还是会往重写缓冲区写一份数据的,当父进程监听到子进程退出的时候,backgroundRewriteDoneHandler函数再把重写缓冲区的文件写入到新aof文件中,写完再重命名,完成了这个操作,就不会有数据丢失了。又不阻塞又不会丢数据,就算是监控子进程这一步挂掉了,也可以继续使用老的aof文件,老的aof文件除了大一点没其他毛病,只能说这个设计思路无敌,又学会了一招。
在这里插入图片描述

总结:子进程在快fork完成时候利用管道告知父进程不要在发送重写缓冲内容了,在重写子进程没完全退出的时候还是会把新来的命令放在重写缓冲区的,重写缓冲区是由双向链表组成。父进程会监控子进程完成的进度,当子进程执行结束后,父进程会把没同步的重写缓冲区的数据写入到新的aof文件中去,这样既没有加锁阻塞新来的redis命令执行,也不会丢失redis命令,设计思路真的棒,又学会了一招。

Redis AOF重写是一种机制,用于解决AOF文件过大导致IO性能问题的情况。AOF重写的过程并不需要对原有AOF文件进行读取、写入分析操作,而是通过读取服务器当前的数据库状态来实现的。\[3\]AOF重写的执行流程包括命令追加、文件写入和文件同步以及文件重写。首先,Redis的写命令会被追加到缓冲区aof_buf中。然后,根据不同的同步策略,将aof_buf中的内容同步到硬盘,以确保数据的持久化。最后,定期进行AOF文件的重写,以达到压缩AOF文件的目的。\[3\]通过AOF重写,可以有效地减小AOF文件的大小,提高IO性能,同时保证数据的持久化。 #### 引用[.reference_title] - *1* *3* [缓存数据库REDIS之二:AOF重写原理](https://blog.csdn.net/qq_18343913/article/details/119343547)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [redisaof重写机制](https://blog.csdn.net/qq_63431773/article/details/131691454)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值