Redis基础 -写时复制技术

 Redis中的fork

        Redis中执行bgsave,bgrewriteaof,即在生成数据库快照和重写aof文件时,为了不堵塞主线程,都会采用fork()系统调用创建一个子进程来,此时子进程与父进程共享相同的物理内存数据,防止 fork 创建子进程时,由于物理内存数据的复制时间过长而导致父进程长时间阻塞的问题。

        但是子进程重写过程中,主进程依然可以正常处理命令。

        如果此时主进程修改了已经存在 key-value,就会发生写时复制,注意这里只会复制主进程修改的物理内存数据,没修改物理内存还是与子进程共享的

        所以如果这个阶段修改的是一个 bigkey,也就是数据量比较大的 key-value 的时候,这时复制的物理内存数据的过程就会比较耗时,有阻塞主进程的风险。

        还有个问题,重写 AOF 日志过程中,如果主进程修改了已经存在 key-value,此时这个 key-value 数据在子进程的内存数据就跟主进程的内存数据不一致了。

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

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

        在整个 AOF 后台重写过程中,除了发生写时复制会对主进程造成阻塞,还有信号处理函数执行时也会对主进程造成阻塞,在其他时候,AOF 后台重写都不会阻塞主进程。

        

写时复制机制优化后的fork

        一个进程在用户态通过系统调用fork来创建一个子进程。

        大致流程时:执行fork函数之后,CPU开始变态,完成变态之后,执行内核方法sys_fork,在这个方法体中调用了do_fork函数,这个函数会在内核空间创建一个子进程的task_struct和页表,因为task_struct和页表包含很多信息,为了提高运行性能,所以直接拷贝父亲进程的task_struct;创建完成之后,将task_struct加入进程链表之中,而后将其唤醒,状态设置为RUNNING,放入到调度队列之中,等待CPU的调度;一旦获得CPU调度之后,会执行exec()方法组,从磁盘中加载自己的ELF文件进内存,并且完成对task_struct和页表的修改,当然exec方法也有可能不运行,表示父子进程执行相同的逻辑。

        此时子进程只需要拷贝父进程的task_struct和页表,而不需要拷贝父进程在物理内存的数据,因为后期执行exec之后,会加载自己的ELF文件进内存中,所以,如果按照上面的做法的话,创建子进程时复制过去的数据是没用的(因为子进程执行exec(),原有的数据会被清空);

     

写时复制的理解:

        在父进程完成fork之后,子进程创建完成,子进程共享父进程的物理内存,这样能够节约物理内存资源,页表对应的页表项的属性会标记该物理内存的权限为只读

        在此期间父子进程是有可能发生写操作的,我们也是允许执行写操作的。

        当父进程进行写操作时,会触发写保护中断,执行相应的中断处理程序,将要修改的页面进行复制,在复制的新页面中进行修改,而后更改页表中地址空间的映射关系。

        当子进程进行写操作时,会触发写保护中断,执行相应的中断处理程序,将要修改的页面进行复制,在复制的新页面中进行修改,该页面属于子进程的内存地址空间,与父进程无关,而后更改子进程页表中地址空间的映射关系。

        在写时复制机制下,fork()的实际开销就是复制父进程的页表以及给子进程创建惟一的进程描述符。

 Redis基础 -写时复制技术_第1张图片

vfork:

        vfork():这个做法更加火爆,内核连子进程的虚拟地址空间结构也不创建了,直接共享了父进程的虚拟空间,当然了,这种做法就顺水推舟的共享了父进程的物理空间

Redis基础 -写时复制技术_第2张图片

相关文章推荐:

(22条消息) 写时复制(Copy On Write)_NeoJoe的博客-CSDN博客_写时复制https://blog.csdn.net/qq_32131499/article/details/94561780?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-94561780-blog-117324852.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-94561780-blog-117324852.pc_relevant_default&utm_relevant_index=2

你可能感兴趣的:(redis,redis,数据库,缓存)