本文范围
实时协同编辑中,每个站点维护共享文档的一个副本。本文将一次插入、删除等编辑请求称为用户操作,将它作用的字符、段落等文档内容称为文档元素;某些算法也将文档元素作为带标识的数据项处理,以下统称为操作对象。操作产生时,站点当前已知操作及其对应的文档内容构成该操作所依据的文档状态。
网络传递存在延迟时,多个站点可能基于不同文档状态产生操作。本文定义分析这种情形所需的因果关系、并发关系、全序和一致性目标。操作转换(OT)、地址空间转换(AST)和可交换的复制式数据类型(CRDT)的机制分类见实时协作算法基本类型。
操作之间的偏序关系
偏序用于描述两个操作之间已经确定的先后依赖,以及它们是否互不知晓。设 Oa 和 Ob 是两个操作:
- 因果关系:记为
Oa → Ob。在同一站点,Oa先于Ob产生;或者Ob产生前,所在站点已经接收并执行了Oa;因果关系还具有传递性。 - 并发关系:记为
Oa || Ob。当Oa → Ob和Ob → Oa都不成立时,二者并发。 - 简单并发:两个并发操作产生于相同的文档状态。
- 偏并发:两个并发操作产生于不同的文档状态。
并发只说明操作之间没有因果顺序,不直接说明操作是否冲突。是否需要调整操作、如何确定操作位置,取决于具体操作语义和算法实现。
统一示例
设站点 A、B、C 的初始文档状态均为 S0。下表只记录操作产生前已知的操作,不涉及插入位置、字符内容或执行结果。
| 操作 | 产生站点 | 产生前已知的操作 | 由此可确定的关系 |
|---|---|---|---|
O1 |
A | 无,状态为 S0 |
O1 与随后基于它产生的操作存在因果关系 |
O2 |
B | O1,站点 B 已接收并执行 O1 |
O1 → O2 |
O3 |
C | 无,状态为 S0 |
`O1 |
O1 与 O3 都基于 S0 产生,属于简单并发。O2 基于已包含 O1 的状态产生,而 O3 基于 S0 产生;二者是偏并发。该示例仅用于判断偏序关系,不能据此推出三个操作的执行顺序或最终文档内容。
全序
偏序保留已知因果关系,却不为并发操作指定先后次序。全序为每对操作或操作对象给出确定的先后次序,并要求这些次序保持一致的传递关系,避免出现循环排序。它可用于排序、重放或在各站点选择相同的处理顺序。全序本身不足以定义编辑语义:插入、删除等用户操作在该顺序下如何执行或转换,仍需由具体算法规定。
**站点编号(siteID)**是用于标识操作来源站点的稳定唯一编号。算法可在其他排序条件无法区分时,以 siteID 作为确定性决胜条件;编号的比较方向和适用条件由算法定义。
操作的全序
操作的全序对操作记录排序。原文将 GOT(Generic Operational Transformation)归为通过状态向量和 siteID 定义操作全序的方案:
- **状态向量(State Vector,SV)**是按站点记录已知操作数量的整数数组;操作关联的状态向量表示它产生时站点已知的操作范围。
- 排序规则可利用状态向量所表达的已知状态,并在需要时使用 siteID 消除并列,从而为操作给出确定次序。
这段说明只限定 GOT 的排序定位,不给出可执行的比较函数,也不说明操作执行、转换或最终文档结果。实现或比较具体 GOT 变体时,需要以相应算法定义为准。
集中式方案也可以由单一服务接收操作并将其序列化,或为操作分配连续序号。该机制使参与者获得同一序列;远程操作在本地文档状态上的解释仍由协同编辑算法规定。
操作对象的全序
操作对象的全序对文档元素或其内部标识符排序。例如,CRDT 可为操作对象维护唯一 ID 和顺序元数据,并用这些元数据确定对象在内部数据结构中的相对位置。这里的对象顺序不同于用户操作的执行顺序;两者都不能脱离算法的操作语义单独推导编辑结果。
一致性目标与操作意图
协同编辑算法通常需要明确以下目标:
- 因果一致性:若
Oa → Ob,各站点在处理二者时应先处理Oa,再处理Ob。 - 结果一致性:当各站点都已处理同一协同会话中同一组已送达、无待处理状态的操作时,各站点的共享文档副本相同。
- 操作意图:用户操作在并发环境中的预期效果。它必须结合操作语义定义,例如插入和删除的对象、位置表示及同位置并发时的处理规则。
操作意图不能由全序、因果关系或结果一致性单独推出。AST 或 CRDT 是否在某个实现中保持操作意图,取决于该实现定义的操作语义、对象标识和并发处理规则;不能仅依据算法类别作出结论。
操作转换的机制边界
OT 以用户操作为处理单位。本地产生的操作可先作用于本地副本;远程操作到达时,系统会根据已经执行的并发操作调整待执行操作的参数,使其能在当前文档状态上解释和执行。转换函数的输入、位置规则及同位置并发时的处理方式均依赖具体应用的操作语义。
OT 的实现通常需要保留与转换相关的操作历史或等价上下文。相比之下,CRDT 不维护 OT 语境中的转换历史,但仍需要维护操作对象的 ID、顺序元数据及算法所需的内部状态。三类算法的处理单位和机制边界见实时协作算法基本类型。

