Redis 源码剖析与实战
蒋德钧
中科院计算所副研究员
17747 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 47 讲
Redis 源码剖析与实战
15
15
1.0x
00:00/00:00
登录|注册

19 | AOF重写(上):触发时机与重写的影响

你好,我是蒋德钧。
我们知道,Redis 除了使用内存快照 RDB 来保证数据可靠性之外,还可以使用 AOF 日志。不过,RDB 文件是将某一时刻的内存数据保存成一个文件,而 AOF 日志则会记录接收到的所有写操作。如果 Redis server 的写请求很多,那么 AOF 日志中记录的操作也会越来越多,进而就导致 AOF 日志文件越来越大。
所以,为了避免产生过大的 AOF 日志文件,Redis 会对 AOF 文件进行重写,也就是针对当前数据库中每个键值对的最新内容,记录它的插入操作,而不再记录它的历史写操作了。这样一来,重写后的 AOF 日志文件就能变小了。
那么,AOF 重写在哪些时候会被触发呢?以及 AOF 重写需要写文件,这个过程会阻塞 Redis 的主线程,进而影响 Redis 的性能吗?
今天这节课,我就来给你介绍下 AOF 重写的代码实现过程,通过了解它的代码实现,我们就可以清楚地了解到 AOF 重写过程的表现,以及它对 Redis server 的影响。这样,当你再遇到 Redis server 性能变慢的问题时,你就可以排查是否是 AOF 重写导致的了。
好,接下来,我们先来看下 AOF 重写函数以及它的触发时机。

AOF 重写函数与触发时机

首先,实现 AOF 重写的函数是 rewriteAppendOnlyFileBackground,它是在aof.c文件中实现的。在这个函数中,会调用 fork 函数创建一个 AOF 重写子进程,来实际执行重写操作。关于这个函数的具体实现,我稍后会给你详细介绍。这里呢,我们先来看看,这个函数会被哪些函数调用,这样我们就可以了解 AOF 重写的触发时机了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Redis AOF重写是通过记录最新的键值对插入操作来减小AOF日志文件的大小。触发时机包括手动执行bgrewriteaof命令、主从复制完成RDB文件解析和加载、AOF重写被设置为待调度执行、AOF文件大小超出阈值。AOF重写函数rewriteAppendOnlyFileBackground的实现和调用方式,以及AOF重写对Redis server性能的影响也在文章中有所介绍。通过设置redis.conf文件中的auto-aof-rewrite-percentage和auto-aof-rewrite-min-size两个阈值,可以让Redis server自动重写AOF文件。文章还介绍了AOF重写的基本执行过程,包括AOF重写子进程和父进程的逻辑,以及父子进程间的通信过程。总之,本文详细介绍了AOF重写的实现过程和触发时机,对于想要深入了解Redis AOF重写的读者来说,是一篇值得阅读的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 源码剖析与实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(5)

  • 最新
  • 精选
  • Kaito
    1、AOF 记录的是每个命令的「操作历史」,随着时间增长,AOF 文件会越来越大,所以需要 AOF 重写来「瘦身」,减小文件体积 2、AOF 重写时,会扫描整个实例中的数据,把数据以「命令 + 键值对」的格式,写到 AOF 文件中 3、触发 AOF 重写的时机有 4 个: - 执行 bgrewriteaof 命令 - 手动打开 AOF 开关(config set appendonly yes) - 从库加载完主库 RDB 后(AOF 被启动的前提下) - 定时触发:AOF 文件大小比例超出阈值、AOF 文件大小绝对值超出阈值(AOF 被启动的前提下) 这 4 个时机,都不能有 RDB 子进程,否则 AOF 重写会延迟执行。 4、AOF 重写期间会禁用 rehash,不让父进程调整哈希表大小,目的是父进程「写时复制」拷贝大量内存页面 课后题:为什么 Redis 源码中在有 RDB 子进程运行时,不会启动 AOF 重写子进程? 无论是生成 RDB 还是 AOF 重写,都需要创建子进程,然后把实例中的所有数据写到磁盘上,这个过程中涉及到两块: - CPU:写盘之前需要先迭代实例中的所有数据,在这期间会耗费比较多的 CPU 资源,两者同时进行,CPU 资源消耗大 - 磁盘:同样地,RDB 和 AOF 重写,都是把内存数据落盘,在这期间 Redis 会持续写磁盘,如果同时进行,磁盘 IO 压力也会较大 整体来说都是为了资源考虑,所以不会让它们同时进行。
    2021-09-09
    5
    18
  • 曾轼麟
    先回答老师的问题:RDB和AOF进程为什么不能同时运行? 答:有多方的原因 1、AOF-RDB混合持久化 现在Redis官方主推的是AOF-RDB混合持久化方案,同时运行AOF进程重写和RDB进程保存必然会带来不必要的冲突。 2、两个都是fork出来的 由于AOF重写进程和RDB保存进程都是通过fork出来的,AOF在重写期间还会继续保存来自主进程的命令操作,那么同时运行必然带来风险也需要考虑更多问题。 3、更高的资源消耗 AOF和RDB都是高IO的操作,而且业务场景也非必须同时进行,同时进行对资源是较大的浪费。 总结: 本次老师介绍了AOF重写是如何进行的,和上一篇文章一样AOF重写是高IO操作,并且是一个异步缓慢的过程为了避免阻塞主进程Redis是通过fork子进程进行的,但是与RDB不同的是AOF重写期间还需要同步重写期间来自主进程的命令,并在重写完成后同步到文件中,在这里老师也引出了管道技术,为AOF进程同步主进程命令买下伏笔(期待老师的下篇文章) 其次值得注意的是updateDictResizePolicy函数,文章中提到updateDictResizePolicy是在AOF进行中调用,目的是为了阻止渐进式Rehash从而减少【写时复制】带来的大量内存开销,除了AOF意外其实bgsave 异步保存RDB文件也会调用这个方法来避免同样的问题。
    2021-09-09
    6
  • William
    这里有疑问,“在父进程中,这个 rewriteAppendOnlyFileBackground 函数会把 aof_rewrite_scheduled 变量设置为 0,同时记录 AOF 重写开始的时间,以及记录 AOF 子进程的进程号。” 我看这是if..else 结构呀? 进来的时候 是 if ((childpid = fork()) == 0) { ....} , 怎么会既有fork子进程重写AOF, 又有父进程,对这个标记调整为0 ? 查到的资料: fock函数调用一次却返回两次;向父进程返回子进程的ID,向子进程中返回0; 所以父子进程的业务逻辑都会执行。 请老师解惑是不是这样?
    2021-09-24
    3
  • 静心
    我有一个疑问没搞明白: 在AOF重写的时候,是新创建一个文件来写,写完之后再替换旧的AOF文件呢?还是重写先在内存中进行,然后再覆盖旧的AOF文件?
    2021-09-15
    1
  • Milittle
    问答题:我的考虑是为了并发安全
    2021-09-09
    1
收起评论
显示
设置
留言
5
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部