本文介绍: 触发重写机制后,主进程就会创建重写 AOF 的子进程,此时父子进程共享物理内存重写进程只会对这个内存进行只读重写 AOF 子进程读取数据库里的所有数据,并逐一把内存数据键值转换一条命令,再将命令记录重写日志(新的 AOF 文件)。简单来说,两者的虚拟空间不同,但其对应的物理空间是同一个。那么问题来了,重写 AOF 日志过程中,如果主进程修改了已经存在的 keyvalue,就会触发「写时复制」,此时这个 keyvalue 数据在子进程的内存数据就和在主进程的内存数据不一致了。

重写 AOF 日志过程是怎样的?

Redis重写 AOF 过程是由后台子进程 bgrewriteaof 来完成的,这么做有以下两个好处。

触发重写机制后,主进程就会创建重写 AOF 的子进程,此时父子进程共享物理内存,重写子进程只会对这个内存进行只读,重写 AOF 子进程会读取数据库里的所有数据,并逐一把内存数据的键值对转换成一条命令,再将命令记录到重写日志(新的 AOF 文件)。

子进程是怎样拥有和主进程一样的数据副本的呢?

主进程在通过 fork 系统调用生成 bgrewriteaof 子进程时,操作系统会把主进程的「页表复制一份给子进程,这个页表记录着虚拟地址和物理地址映射关系,而不会复制物理内存。简单来说,两者的虚拟空间不同,但其对应的物理空间是同一个

在这里插入图片描述

这样一来,子进程就共享了父进程的物理内存数据,这样能够节约物理内存资源页表对应的页表项的属性标记该物理内存的权限为只读。

不过,当父进程或者子进程在向这个内存发起写操作时,CPU 就会触发保护中断,这个写保护中断是由于违反权限导致的,然后操作系统会在「写保护中断处理函数」里进行物理内存的复制,并重新设置其内存映射关系,将父子进程的内存读写权限设置为可读写最后才会对内存进行写操作,这个过程被称为「写时复制」。

在这里插入图片描述

注意,这里只会复制主进程修改的物理内存数据,没修改的物理内存还是与子进程共享的。

但是在重写过程中,主进程依然可以正常处理命令。那么问题来了,重写 AOF 日志过程中,如果主进程修改了已经存在的 keyvalue,就会触发「写时复制」,此时这个 keyvalue 数据在子进程的内存数据就和在主进程的内存数据不一致了。

为了解决这种数据不一致的问题,Redis 设置了一个 AOF 重写缓冲区,这个缓冲区创建 bgrewriteaof 子进程之后开始使用。

在重写 AOF 期间,当 Redis 执行一个写命令之后,它会同时将这个写命令写入到 「AOF 缓冲区」和 「AOF 重写缓冲区」。

在这里插入图片描述

也就是说,在 bgrewriteaof 子进程执行 AOF 重写期间,主进程需要执行以下三个工作

当子进程完成 AOF 重写工作扫描数据库中的所有数据,逐一把内存数据的键值对转换成一条命令,再将命令记录到重写日志)后,会向主进程发送一条信号信号是进程间通讯的一种方式,且是异步的)。

主进程收到信号后,会调用一个信号处理函数,该函数主要做以下工作

  1. 将 AOF 重写缓冲区中的所有内容追加到新的 AOF 文件中,使得新旧两个 AOF 文件保存的数据状态一致
  2. 对新的 AOF 的文件进行改名,覆盖现有的 AOF 文件

信号函数执行完后,主进程就可以继续像往常一样处理命令了。

原文地址:https://blog.csdn.net/qq_43665821/article/details/132500584

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_11947.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注