【文档协同编辑】(一) OT算法
背景
Operational Transformation(OT)算法是一种用于实时协同编辑的算法。它是通过将用户操作转换为操作序列并将其应用于文档来实现多用户同时编辑文档的一致性的。
在多用户同时编辑文档时,每个用户的操作将会相互影响,可能会导致冲突。为了解决这个问题,OT算法通过将用户操作转换为操作序列并对操作序列进行变换,以便使得多个操作序列应用后的结果达到一致,从而解决冲突问题。
虽然目前大多数互联网公司使用的是OT算法实现,但是OT算法存在中心服务器性能的问题,而CRDT去中心化,长远来看发展前景超过了OT,因此这里对OT算法不做详细介绍。
分类
具体来说,OT算法会对操作进行分类,将操作分为transformable和non-transformable两种类型。transformable操作可以通过OT算法进行变换,使得操作序列最终产生的结果是一致的。而non-transformable操作则需要额外的处理,例如通过禁止用户同时进行这些操作来避免冲突。
OT算法在实时协同编辑领域得到了广泛应用,例如Google Docs和Microsoft Office Online,WPS等在线协同编辑工具都采用了OT算法来实现多用户同时编辑文档的一致性。
状态转换:OT算法主要有三种状态:Synchronized、AwaitingConfirm、AwaitingWithBuffer。当client没有发送请求时,则处于Synchronized状态,当client请求未响应时,则处于AwaitingConfirm状态,当client处于AwaitingConfirm,且client不断生成新动作时则转换为AwaitingWithBuffer状态。
冲突处理是指定义转换规则,在发生编辑冲突时,将动作转换为无冲突的动作。假定A和B分别是来自不同client且基于同一版本数据所做的操作,A'和B'分别是A和B经过ot处理的输出,则OT的核心在于保证公式 apply(apply(S, A), B') = apply(apply(S, B), A') 的成立,否则无法保证各个client的数据一致性。基于以上公式,我们对xmind的添加、删除、更新和拖拽节点四种操作,以及节点之间父亲、兄弟、相同节点、儿子结点四种关系分析了4 × 4 × 4 = 64种冲突场景并设计转换规则。
动作合并:动作合并是指将在buffer中的动作进行精简。
场景
架构
OT的应用交互是服务端统一处理并返回到浏览器。在两个用户A,B编辑同一个文本的情况下,A,B的浏览器会先执行自己的操作,但是服务器收到另外的操作需要进行处理,如果不加处理,客户端得到的文本是不一样的。为了A和B能看到一样的结果,每个客户端执行完本地操作后,会再执行转换过的另一个客户端的操作。
OT算法的分布式理论
OT的操作转换可以是简单的线性文本,但是还有其他的更加复杂的如表格,树形结构,而且在一个成熟可用的产品中还要考虑到websocket的架构,在不同的终端网络变化的情况。在大规模协同的情况下,还要考虑编辑的网络和存储性能。
OT系统的数据模型定义了文档中的数据对象相互关联并被操作的方式。不同的OT系统可能具有不同的数据模型。例如,基本OT系统的数据模型是由单个线性地址空间中寻址的独立对象。这个基本数据模型足以对一维和线性有序的数据对象进行建模,例如字符序列(在纯文本文档中)、PPT序列等。基本OT数据模型已扩展到多个线性寻址领域的层次,以支持文字处理器和HTML/XML文档,包括依赖图用于支持数字媒体文档。
OT的目的是为了保证最终一致性。而最终一致性是分布式系统的老问题,形式化的证明需要参照Lamport老爷子的Happen before关系。
开源项目
业界有对OT算法的实现框架:ot.js,其主要是实现文本的OT,但思想的框架可以为我们所用,不局限于表格、文本,可以用在脑图等其他文档的协同编辑中。
Reference
https://www3.ntu.edu.sg/scse/staff/czsun/projects/otfaq/
https://zhuanlan.zhihu.com/p/30890457
https://hal.inria.fr/inria-00432368/document