Kaito
2021-09-09
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 压力也会较大 整体来说都是为了资源考虑,所以不会让它们同时进行。
展开
共 5 条评论
17
曾轼麟
2021-09-09
先回答老师的问题: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文件也会调用这个方法来避免同样的问题。
展开
6
William
2021-09-24
这里有疑问,“在父进程中,这个 rewriteAppendOnlyFileBackground 函数会把 aof_rewrite_scheduled 变量设置为 0,同时记录 AOF 重写开始的时间,以及记录 AOF 子进程的进程号。” 我看这是if..else 结构呀? 进来的时候 是 if ((childpid = fork()) == 0) { ....} , 怎么会既有fork子进程重写AOF, 又有父进程,对这个标记调整为0 ? 查到的资料: fock函数调用一次却返回两次;向父进程返回子进程的ID,向子进程中返回0; 所以父子进程的业务逻辑都会执行。 请老师解惑是不是这样?
共 2 条评论
静心
2021-09-15
我有一个疑问没搞明白: 在AOF重写的时候,是新创建一个文件来写,写完之后再替换旧的AOF文件呢?还是重写先在内存中进行,然后再覆盖旧的AOF文件?
共 1 条评论
Milittle
2021-09-09
问答题:我的考虑是为了并发安全
共 1 条评论