Skip to content

文章翻译

为什么 AFFiNE 选择 CRDT 而非 OT 来构建协作编辑器#

原文地址:https://medium.com/@affineworkos/why-affine-chose-crdt-over-ot-to-build-a-collaborative-editor-14b05689584c#e71f

译者注:

AFFiNE 是一个开源的现代化协同文档编辑器项目,该项目采用了 Notion + Miro + Obsidian 的混合风格,强调:

  • 支持多人协作
  • 支持本地编辑
  • 支持 markdown + 富文本 + 白板
  • 基于 CRDT 技术实现同步

AFFiNE 目标是构建一个“本地优先、支持多人实时协作、集文档、白板、任务于一体”的全功能办公工具。

image-20250409135055820

这篇文章会介绍 Affine 为什么选择 CRDT 而非 OT,用来实现更出色的实时协作,确保高可用性、强大的容错性以及轻松扩展能力,从而推动业务成功。

作为一款支持多用户实时协作的编辑器,AFFiNE 在数据可用性方面面临三大挑战:

上述问题在协作类应用中非常常见,因此其解决方案应通过某种通用的协作算法来保障可靠性。过去三十年间,研究人员提出了数百种协作算法,但大多可以归为两类:Operational Transform(OT)Conflict-free Replicable Data Type(CRDT)。我们认为,当前更优的选择是 CRDT

OT 与 CRDT 的定义与区别#

如果你把“追溯历史状态”视为最基础的协作能力之一,那么你会发现 event sourcing 设计模式几乎是所有协作能力的起点。该模式要求我们将对数据模型的操作抽象为可序列化的操作(或命令)数据结构。例如,Web 开发者熟知的 Redux 库就是 event sourcing 模式的典型实现。

在多人实时协作的场景中,挑战主要来自这样一个情况:在任意时刻,不同用户的操作可能会产生分歧。但从 event sourcing 的视角来看,我们始终在处理两类数据结构:modeloperation。据此可以认为,OT 的核心在于对 operation 数据的转换,通过转换后的 operation 数据可以在不同客户端的普通 model 上应用;而 CRDT 的核心是设计一种对并发操作友好的 model,使得不同客户端可以在任意时间顺序下合并操作。

尽管现在有观点认为 OT 与 CRDT 在理论基础上本质一致,但我们认为,上述这种对比仍然是理解这两种机制的一个实用思维模型。

我们为何更倾向于选择 CRDT#

在 CRDT 中,每次更新都可以看作是一个“历史片段”。我们不断从其他客户端收集这些片段,并依靠片段中携带的逻辑时间戳来还原出最终一致的真实状态。我们认为,CRDT 的这种工作机制相较于 OT 具有以下三大优势。

去中心化#

由于 CRDT 的数据模型被设计为可以在任意客户端独立解决冲突,因此无需引入中心节点来唯一确定操作的合并顺序。这不仅降低了对单一服务端节点的依赖,还为构建下一代 local-first 应用架构提供了可能——这种架构融合了传统本地应用与协作应用的优点,甚至在技术上也支持端到端加密的协作方式。

性能表现#

尽管早期为学术研究而设计的 CRDT 实现曾被认为性能较差,但近年来经过业界的优化,CRDT 的吞吐量已超越传统 OT 实现,内存占用也已降至可接受的水平。同时,由于 CRDT 的去中心化特性,它具备更高的延迟容忍度,能够在更长时间离线后依然完成冲突解决。相比之下,在相同条件下 OT 的计算压力往往会给服务端带来较大负担。

灵活性与易用性#

CRDT 支持更广泛的数据类型。例如,Yjs 支持 Text、Array、Map 以及类树形结构的数据,使其适用于更多业务场景。由于支持的数据类型更多,CRDT 在扩展性方面通常也更具优势。相比之下,OT 库要求开发者将业务逻辑彻底建模为不同类型的 operation 数据结构,而使用 CRDT 库时,你只需对常见的数据结构(如 Map 和 Array)执行相同的操作,它们会被自动映射到对应的 CRDT 模型上。

在某种程度上,这就像是使用一个更强大、更易用的应用 state 管理 API,有点类似 Redux 的作用,但整体接入成本更低。

总结#

协作算法对许多开发者来说仍然比较陌生。尽管相关的概念性介绍已有不少,但关于如何实际使用这些算法的清晰说明仍然较为匮乏。如果你也正处于初创阶段,正在开发一款编辑器,并希望就此获得一些建议,我们的看法是:CRDT,特别是目前的 Yjs,实现,已经是非常值得考虑的选项


-EOF-