当前位置: 首页 > news >正文

CopyOnWrite


集合类中的COW



redis 中的 COW


Redis 中广泛运用了 Copy-on-Write (COW) 的思想,但它的实现目的和场景与 Java 中的 CopyOnWriteArrayList 有相同之处,也有不同之处。

Redis 的 COW 机制主要服务于以下两个核心功能:

  1. 持久化(Persistence):在生成 RDB 快照时。
  2. 数据复制(Replication):在主从节点同步数据时。

1. 在 RDB 持久化中的 COW


当 Redis 需要执行 SAVEBGSAVE 命令来创建当前数据的快照(一个 .rdb 文件)时,COW 就开始发挥作用。

  • SAVE:会阻塞服务器进程,直到 RDB 文件创建完毕。这个过程不会使用 COW,因为整个过程中服务器不处理任何命令,内存数据不会被改变。
  • BGSAVE:会 fork() 一个子进程来在后台创建 RDB 文件,父进程(主服务器进程)继续处理命令。这里就是 COW 的经典应用场景

BGSAVE** 的工作流程:**

  1. 父进程调用 fork(),创建一个子进程。
  2. 此时,子进程和父进程共享相同的内存数据页
  3. 子进程的任务是将整个数据库的数据写入到一个临时的 RDB 文件中。
  4. 在子进程写入的过程中,如果父进程接收到了新的命令,需要修改某块数据(例如执行 SETLPUSH 等)。
  5. 操作系统会运用 Copy-on-Write 机制:内核会将被修改的内存页复制一份副本,然后父进程在这个副本上进行修改。而子进程读取的仍然是 fork() 瞬间的那个未修改的内存页。
  6. 这样子进程就能看到的是一个在 fork() 时刻的、凝固不变的数据快照,可以安心地将其序列化到 RDB 文件。而父进程也可以继续正常服务,不受影响。

总结: Redis 利用操作系统的 fork() 和 COW 机制,实现了非阻塞的后台快照功能,保证了数据一致性的同时,性能极高。


2. 在主从复制中的 COW


当一个新的从节点(Slave)连接到主节点(Master)并发起首次同步(full resynchronization)时,过程与 BGSAVE 非常相似:

  1. 主节点启动一个后台保存进程,生成 RDB 快照文件。
  2. 同时,它开始缓冲从开始生成 RDB 起接收到的所有新的写命令。
  3. 后台保存进程完成后,主节点将 RDB 文件发送给从节点。
  4. 从节点接收并加载 RDB 文件,将自己的状态更新到主节点开始生成 RDB 时的状态。
  5. 主节点再将缓冲区的所有写命令发送给从节点执行,从而使从节点的数据与主节点完全同步。

在这个过程的第 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 的核心价值:通过牺牲写操作的性能(延迟复制、空间换时间)来提升读操作的并发性能和数据安全。


文章转载自:

http://yEjFIyiS.wqhLj.cn
http://TexmI5yt.wqhLj.cn
http://QdXLgQ8j.wqhLj.cn
http://VH0jfLo2.wqhLj.cn
http://Q8Zu9y8C.wqhLj.cn
http://W4gbz9eE.wqhLj.cn
http://zpbaiG3g.wqhLj.cn
http://gIjHJSeR.wqhLj.cn
http://pwtQp26Q.wqhLj.cn
http://iwKfdbah.wqhLj.cn
http://YjlDVqdn.wqhLj.cn
http://FL6HH3AO.wqhLj.cn
http://YbnWlLY1.wqhLj.cn
http://zoI9cete.wqhLj.cn
http://Oduhy8q3.wqhLj.cn
http://pUqRkFK4.wqhLj.cn
http://z041gA40.wqhLj.cn
http://cmdRRZ2J.wqhLj.cn
http://0eut6Chp.wqhLj.cn
http://NEw1v7CZ.wqhLj.cn
http://zogKYLwa.wqhLj.cn
http://lRcGphw2.wqhLj.cn
http://JvfOQEJC.wqhLj.cn
http://dDF2vi1S.wqhLj.cn
http://TqSVACOg.wqhLj.cn
http://CSrZvmZl.wqhLj.cn
http://YjmZR7bb.wqhLj.cn
http://10AH4hcr.wqhLj.cn
http://yI5KNWkF.wqhLj.cn
http://nWufFew1.wqhLj.cn
http://www.dtcms.com/a/382962.html

相关文章:

  • 【Ambari监控】监控数据接口查询方法
  • shell 脚本:正则表达式
  • 可调精密稳压器的原理
  • Altium Designer(AD)PCB打孔
  • React 状态管理
  • [Spring Cloud][5] 注册中心详解,CAP 理论,什么是 Eureka
  • 返利app的跨域问题解决方案:CORS与反向代理在前后端分离架构中的应用
  • C++算法题—图的邻接矩阵输入形式(I\O)
  • 主动性算法-如何让机器拥有嗅觉?
  • Knockout.js Google Closure Compiler 工具模块详解
  • 从关键词匹配到语义理解:6大Embedding技术如何重塑企业搜索
  • 【面试实录01】
  • Docker 容器化部署核心实战——镜像仓库管理与容器多参数运行详解
  • Jenkins的安装与简单使用
  • Step-by-Step:用C语言构建一个带精准错误提示的括号匹配器
  • 【LeetCode - 每日1题】元音拼写检查器
  • KingbaseES读写分离集群架构解析
  • 教育领域大模型生成题目安全研究报告
  • .Net程序员就业现状以及学习路线图(七)
  • uniapp如何使用本身的字体图标
  • Uniapp崩溃监控体系构建:内存泄漏三维定位法(堆栈/资源/线程)
  • window显示驱动开发—显示适配器的子设备
  • 单变量单步时序预测 | TCN-BiGRU时间卷积神经网络结合双向门控循环单元
  • 项目实战——“微商城”前后台【005】之前台项目首页编写
  • 如何利用redis使用一个滑动窗口限流
  • Go与Python/PHP的比较
  • JVM 运行时数据区详解:程序计数器、虚拟机栈、堆内存、方法区与直接内存
  • MongoDB $type 操作符
  • 【靶场练习】--DVWA第一关Brute Force(暴力破解)全难度分析
  • ConcatenationShortcut