文档协同,也就是多个人同时编辑同一份文档。允许 多个用户 在 不同的设备 对 同一份文档 进行编辑。
随着云计算和互联网技术的发展,文档协同逐渐成为了团队合作、远程办公、在线教育等领域中不可或缺的一部分。通过实时的同步和更新,协同编辑不仅能够提高团队的工作效率,还能够加强成员间的互动和沟通。
文档协同系统需要解决的问题:就是如何有效地管理多个用户对同一文档的并发操作。
- 如何防止冲突
- 如何保证数据的一致性
- 如何实时的同步文档的修改给其他用户
常见的方式,包括:
- 读写锁
- diff-patch合并
- 自动合并冲突算法:OT 和 CRDT
读写锁#
读写锁是一种经典的 同步机制,在文档协同场景中用于管理用户对同一份文档的访问权限。其基本思想是通过**写锁(Write Lock)和读锁(Read Lock)**的划分,控制文档的编辑与查看权限,从而避免冲突、提升协同效率。
- ✍️ 写锁(Write Lock):当一个用户获取到文档的写锁时,表示该用户正在对文档进行编辑操作。在此期间,系统禁止其他用户对该文档进行修改。
- 👁️ 读锁(Read Lock):当某个用户正在编辑文档(即文档处于写锁状态)时,其他用户虽然不能对文档进行修改,但仍然可以以 只读的方式 访问文档内容。系统在逻辑上视这些用户为持有“只读访问权限”,但不参与写锁的竞争。这种设计确保了数据的一致性,同时提升了并发读取的体验。
🔑读写锁的核心概念
-
加锁与释放
- 加锁:某个用户进入编辑状态的时候,系统会为该文档加上写锁
- 释放:用户已经编辑完了,就会将写锁释放掉。
-
锁的争用:多个用户同时尝试编辑文档,一般来讲即便多个用户同时点击编辑,时间戳还是有细微区别的,可以根据时间戳来判断将写锁给谁。时间戳也一样,根据其他的判定条件,例如用户ID
-
并发读取:多个用户可以并发的去访问文档,但仅仅只是阅读,无法修改。
操作系统级的读写锁 和 文档协同级别的读写锁 区别:
- 操作系统的读写锁:写锁的时候禁止读操作,读锁的时候允许多个读操作但是禁止写操作。
- 文档协同级别的读写锁:即便文档处于写锁,其他用户也可以读取文档内容,只是不能编辑。
✅ 优点
- 实现简单
- 避免冲突
- 读取具备并发性
⚠️缺点
- 编辑阻塞,造成饥饿现象:所谓“饥饿现象”,指的是一个用户长时间占有写锁,其他用户长时间处于无法编辑的状态。
- 用户体验下降
- 扩展性有限
针对上述的缺点,会有一些优化策略:
- 锁超时机制,超过一定的时间一直没有编辑,会自动释放锁
- 优先队列机制
- 段级锁定:锁定文档某个部分,而非整篇文档
📘 读写锁的适用场景
- 对实时性要求不高
- 内容稳定、变动频率低:文档 90% 的场景是查看,偶尔需要编辑
- 强调强一致性要求:在需要严格保证数据一致性的场景中(如审批流程文档),读写锁可以通过排他性写入机制避免并发冲突。
读写锁作为一种简单而有效的协作控制机制,在许多文档协同系统的 早期阶段 中被广泛采用。它通过在编辑期间对文档加锁,确保仅有一个用户可以进行修改,其余用户则处于只读状态,从而有效防止并发修改造成的数据冲突或内容覆盖。
然而,随着多人协同编辑需求的增强,传统的读写锁机制暴露出诸如编辑阻塞、锁争用、响应延迟等问题,难以满足高并发场景下的流畅体验。为了解决这些问题,现代协同编辑系统逐渐采用更先进的协同方式。
diff-patch合并#
diff-patch 合并通过计算文档差异来合并不同用户的修改:
- diff:比较两个版本的文件之间的差异
- patch:根据具体的差异来对文档进行更新
类似于 Git 中合并冲突的过程。
在 Git 中,如果开发者提供的是增量的代码改动,Git 可以自动的合并,如果是有冲突的代码,那么需要开发者手动介入。

🔑diff-patch 合并核心概念
diff-patch 合并方案的工作原理类似于对比两份文档,找出它们之间的变化,然后把这些变化合并成一份最终的文档。
- diff:当多个用户同时编辑文档时,系统会把每个用户的编辑内容与当前的原始文档进行对比,找出这次修改与原文之间的差异。
- patch:在计算出差异之后,系统会生成补丁(patch),即一种格式化的更新,告诉系统“如何将某个版本的文档更新为另一个版本”。
- 冲突检测与人工合并:对于一些无法自动合并的修改部分,系统会提示用户手动选择如何解决冲突。
✅ 优点
- 实现简单:相比后面要介绍的OT以及CRDT,相对来讲更加简单,但是相比前面的读写锁来讲又稍微复杂一点。
- 版本可追溯
- 不阻止并发编辑:和读写锁不同,diff-patch是存在并发编辑的。这也就意味着文档一定会存在差异,这种差异如果是增量的,那么可以自动合并,如果无法自动合并的部分,需要用户手动解决冲突。
- 带宽占用小
⚠️缺点
- 冲突需人工处理
- 合并精度有限
- 冲突区域难以管理
📘diff-patch 合并的适用场景
- 小范围协作编辑:适用于文档修改不那么频繁、冲突较少、团队较小。
- 对文档结构稳定的内容更新
- 异步协作与离线编辑
- 注重版本可追溯性的场景
总结一下:diff-patch 是一种轻量级、实现成本低的文档协同合并策略,尤其适用于修改频率适中、协同规模有限的非实时协作场景。它支持一定程度的并发编辑,并能清晰标记冲突区域以供人工解决。
尽管在高频编辑、实时性强的多人协同中,其人工干预成本和冲突处理负担较高,但作为“Git 风格”协作的核心组件,diff-patch 仍被广泛用于代码编辑器、版本管理平台、CMS 等工具中,是一种在合理边界内极具性价比的方案。
自动合并#
随着协同编辑需求的复杂化,特别是对实时多人编辑的需求逐渐提升,上面两种解决方案无法满足真正意义上的协同编辑。
- 锁机制:限制同时只能一人编辑,别人编辑时也只能干等着
- diff-patch 虽然可行,但需要额外的操作步骤和成本,每次合并需要用户来处理,实时性很差,不适合高频同时修改的场景。特别是针对同一份文档。
于是出现了 OT 和 CRDT 这两种冲突合并算法,它们是专门用于解决并非冲突,并且自动合并的核心技术,非常适用于文档协同的场景。
OT
英语全称为 Operational Transformation,翻译成中文为“操作转换”。
OT 是一种专门为多用户协作编辑设计的算法,它的核心思想是:每个用户对文档进行的修改都可以被转换为一系列操作,这些操作在传播给其他用户时,通过变换操作来保证最终的文档一致性。
OT 主要用于需要 强实时同步的应用,像 Google Docs 就是基于 OT 实现的。它保证了不同用户的修改可以无缝地合并,而不需要人工干预。
CRDT
英语全称为 Conflict-Free Replicated Data Types,翻译成中文的意思是“冲突自由复制数据类型”
它的核心原则是:通过 设计一种特殊的数据结构,使得多个副本之间的更新能够自动合并,而不必担心冲突。
在 CRDT 中,每个节点(用户)都会独立地修改文档,然后通过一种合并算法将这些修改同步到其他节点。
CRDT 适用于 去中心化 和 分布式系统的场景,比如多端同步、离线编辑等。它的优势在于能在 不依赖集中式服务器 的情况下,自动处理文档的并发修改。
✅ 优点
自动合并修改,减少了锁竞争的压力,还能提供良好的用户体验,尤其是在多人协作时避免了数据冲突和锁阻塞问题。
📘适用场景
对于实时协作、去中心化等高并发的协同场景,OT 和 CRDT 算法是最理想的解决方案。
-EOF-