Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

为什么 Redis 持久化使用子进程 · Why's THE Design? · /whys-the-design-redis-bgsave-fork #165

Closed
draveness opened this issue Dec 17, 2019 · 25 comments

Comments

@draveness
Copy link
Owner

draveness commented Dec 17, 2019

https://draveness.me/whys-the-design-redis-bgsave-fork

@arrayadd
Copy link

java 中针对读多写少场景也提供了一种同名的机制,例如CopyOnWriteArrayList。但是看源码,写的时候是真正的复制出一个数组来,使用时候还真要注意实际场景,了解机制背后的“Why’s THE Design”非常重要,感谢楼主系列。

public boolean add(E e) {
		//写时候加锁
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            //复制一份数据
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

@draveness
Copy link
Owner Author

java 中针对读多写少场景也提供了一种同名的机制,例如CopyOnWriteArrayList。但是看源码,写的时候是真正的复制出一个数组来,使用时候还真要注意实际场景,了解机制背后的“Why’s THE Design”非常重要,感谢楼主系列。

这确实会让人对『写时复制』造成误解,有歧义的命名可能会导致很多问题,感谢支持。

@yuanjize
Copy link

“共享内存”指的是哪些内存,是堆吗。

@draveness
Copy link
Owner Author

“共享内存”指的是哪些内存,是堆吗。

不止包括堆,栈、数据段等都会共享

@leafduo
Copy link

leafduo commented Dec 20, 2019

第一次了解到 copy-on-write 是在文件系统里,例如 btrfs 等

@GavinCruise
Copy link

GavinCruise commented Jan 6, 2020

@draveness

java 中针对读多写少场景也提供了一种同名的机制,例如CopyOnWriteArrayList。但是看源码,写的时候是真正的复制出一个数组来,使用时候还真要注意实际场景,了解机制背后的“Why’s THE Design”非常重要,感谢楼主系列。

这确实会让人对『写时复制』造成误解,有歧义的命名可能会导致很多问题,感谢支持。

Java 里的 CopyOnWriteArrayList 属于 CoW 容器,更像是借用了写时复制思想为并发读做的一种解决方案,以 CopyOnWrite 命名也还行

@GavinCruise
Copy link

Docker 中从 image 构建 container 也是用到了 copy-on-write 机制。同样感谢博主这一系列文章,受益匪浅~

@rzzdy
Copy link

rzzdy commented Jan 17, 2020

@draveness

“共享内存”指的是哪些内存,是堆吗。

不止包括堆,栈、数据段等都会共享

像输出缓冲区这种也是共享的么,fork后,子进程再继承一份?

@selboo
Copy link

selboo commented Jan 17, 2020

相关文章里面的
013 为什么 UDP 头只有 8 个字节 连接不对, 打不开

应该是 whys-the-design-udp-minimum-header 吧

@draveness
Copy link
Owner Author

@rzzdy

@draveness

“共享内存”指的是哪些内存,是堆吗。

不止包括堆,栈、数据段等都会共享

像输出缓冲区这种也是共享的么,fork后,子进程再继承一份?

fork 确实会『复制』一份输出缓冲区,但是『再继承一份』是指?

@draveness
Copy link
Owner Author

@selboo
相关文章里面的
013 为什么 UDP 头只有 8 个字节 连接不对, 打不开

应该是 whys-the-design-udp-minimum-header 吧

感谢,已经在发布了

@draveness draveness changed the title 为什么 Redis 持久化使用子进程 · Why's THE Design? 为什么 Redis 持久化使用子进程 · Why's THE Design? · /whys-the-design-redis-bgsave-fork Feb 4, 2020
@vampire007
Copy link

首先感谢博主分享~ 本文中您提到了 rdb 快照机制,能否再介绍下redis aof 的机制呢?

@draveness
Copy link
Owner Author

首先感谢博主分享~ 本文中您提到了 rdb 快照机制,能否再介绍下redis aof 的机制呢?

AOF 其实不是这篇文章的想要回答的问题,你有什么关于 AOF 的问题么?

@Coolxc
Copy link

Coolxc commented Apr 17, 2020

请问RDB中fork的子进程是不是就永远不会复制内存了,因为生成快照并且保存到磁盘这一过程不会出现写操作

@draveness
Copy link
Owner Author

请问RDB中fork的子进程是不是就永远不会复制内存了,因为生成快照并且保存到磁盘这一过程不会出现写操作

父进程可能会写入,这是会触发内存页的复制

@xing393939
Copy link

为什么不能另外起一个线程而是子进程来快照呢?

@draveness
Copy link
Owner Author

为什么不能另外起一个线程而是子进程来快照呢?

先看看进程和线程的区别

@OrdinaryYZH
Copy link

@draveness

为什么不能另外起一个线程而是子进程来快照呢?

先看看进程和线程的区别

个人理解是:可以,但是吞吐量会降低,没必要。

我也好奇LZ的解释是什么呢?

@OrdinaryYZH
Copy link

OrdinaryYZH commented May 16, 2020

@draveness

首先感谢博主分享~ 本文中您提到了 rdb 快照机制,能否再介绍下redis aof 的机制呢?

AOF 其实不是这篇文章的想要回答的问题,你有什么关于 AOF 的问题么?

AOF的重写,也会使用了fork,所以文章中的内容还是对理解aof的重写有作用的,参考:https://redisbook.readthedocs.io/en/latest/internal/aof.html#id13

@draveness
Copy link
Owner Author

@draveness

为什么不能另外起一个线程而是子进程来快照呢?

先看看进程和线程的区别

个人理解是:可以,但是吞吐量会降低,没必要。

我也好奇LZ的解释是什么呢?

线程会共享内存可能还需要处理竞争条件的问题,进程有独立的内存空间,实现上会简单很多。

@MalcolmSanders
Copy link

@xing393939
为什么不能另外起一个线程而是子进程来快照呢?

如果用线程来做快照,在做快照的过程中,所有写操作会立即对redis状态产生影响,这样最终做出来的快照整体上就不是全局一致的了,即可能出现一个快照中,有些部分的数据较新(在快照阶段后期持久化),有些数据版本更老(在快照阶段前期持久化)。

@OrdinaryYZH
Copy link

@MalcolmSanders

@xing393939
为什么不能另外起一个线程而是子进程来快照呢?

如果用线程来做快照,在做快照的过程中,所有写操作会立即对redis状态产生影响,这样最终做出来的快照整体上就不是全局一致的了,即可能出现一个快照中,有些部分的数据较新(在快照阶段后期持久化),有些数据版本更老(在快照阶段前期持久化)。

想了下,好像是这个道理,因为cow,所以容易实现某一个时间的快照

@dayuange123
Copy link

redis 主从复制 需要rdb,但是怎么保证从节点加载rdb后。后续收到的命令恰好是这个rdb之后的命令呢?如果命令重复或者丢失 也会不一致把

@ghaoxiangzZ
Copy link

请问博主写时复制 是以页为单位全量复制吗?还是复制有数据变更的页,无变更的页另外处理

@BrianQy
Copy link

BrianQy commented Nov 6, 2021

AOF和RDB的fork子进程的行为特点有什么不同嘛

Repository owner locked and limited conversation to collaborators Mar 21, 2022
@draveness draveness converted this issue into discussion #580 Mar 21, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests