尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

CopyOnWrite

CopyOnWrite 集合类中的COWCOWCopy‑On‑Write写时复制。核心思想读的时候直接读原容器修改的时候不直接改原数组而是复制一份新副本在副本上修改修改完成后把容器内部引用指向新副本。Java 里典型实现CopyOnWriteArrayList、CopyOnWriteArraySet。Redis 中的 COWRedis 中广泛运用了 Copy-on-Write (COW) 的思想但它的实现目的和场景与 Java 中的CopyOnWriteArrayList有相同之处也有不同之处。Redis 的 COW 机制主要服务于以下两个核心功能持久化Persistence在生成 RDB 快照时。数据复制Replication在主从节点同步数据时。1. 在 RDB 持久化中的 COW当 Redis 需要执行SAVE或BGSAVE命令来创建当前数据的快照一个.rdb文件时COW 就开始发挥作用。SAVE会阻塞服务器进程直到 RDB 文件创建完毕。这个过程不会使用 COW因为整个过程中服务器不处理任何命令内存数据不会被改变。BGSAVE会fork()一个子进程来在后台创建 RDB 文件父进程主服务器进程继续处理命令。这里就是 COW 的经典应用场景。BGSAVE的工作流程父进程调用fork()创建一个子进程。此时子进程和父进程共享相同的内存数据页。子进程的任务是将整个数据库的数据写入到一个临时的 RDB 文件中。在子进程写入的过程中如果父进程接收到了新的命令需要修改某块数据例如执行SET、LPUSH等。操作系统会运用Copy-on-Write机制内核会将被修改的内存页复制一份副本然后父进程在这个副本上进行修改。而子进程读取的仍然是fork()瞬间的那个未修改的内存页。这样子进程就能看到的是一个在fork()时刻的、凝固不变的数据快照可以安心地将其序列化到 RDB 文件。而父进程也可以继续正常服务不受影响。总结Redis 利用操作系统的fork()和 COW 机制实现了非阻塞的后台快照功能保证了数据一致性的同时性能极高。2. 在主从复制中的 COW当一个新的从节点Slave连接到主节点Master并发起首次同步full resynchronization时过程与BGSAVE非常相似主节点启动一个后台保存进程生成 RDB 快照文件。同时它开始缓冲从开始生成 RDB 起接收到的所有新的写命令。后台保存进程完成后主节点将 RDB 文件发送给从节点。从节点接收并加载 RDB 文件将自己的状态更新到主节点开始生成 RDB 时的状态。主节点再将缓冲区的所有写命令发送给从节点执行从而使从节点的数据与主节点完全同步。在这个过程的第 1 步主节点生成 RDB 文件通常也是通过fork()一个子进程来完成的同样利用了 COW 机制来保证子进程生成的数据快照的一致性同时主进程可以继续处理命令。与 Java CopyOnWriteArrayList 的对比特性Java CopyOnWriteArrayListRedis (BGSAVE/Replication)实现层面语言层面在 JVM 中通过代码逻辑创建新数组实现。系统层面依赖操作系统Linux的fork()和 COW 机制。复制单位整个数组Object[]。内存页通常为 4KB。触发时机每次写操作add, set, remove时主动复制。fork()时不立即复制只有在父进程修改数据时才由操作系统被动复制被修改的页。主要目的并发安全保证遍历迭代器不失效避免ConcurrentModificationException。持久化/复制生成某一时刻的一致性数据快照用于备份或同步。读写影响写操作性能开销大复制全集读操作无锁性能极高。fork()本身很快但如果父进程大量写操作会导致大量内存页被复制内存占用可能翻倍。结论Redis 深度依赖 Copy-on-Write 思想但它巧妙的之处在于借用了操作系统内核提供的现成机制而不是自己在应用层重新实现。这使得它的持久化和复制功能非常高效和优雅。无论是 Java 的 COW 容器还是 Redis 的持久化它们都完美体现了 COW 的核心价值通过牺牲写操作的性能延迟复制、空间换时间来提升读操作的并发性能和数据安全。
返回列表