“另有永不删除的头哨兵 $\mathsf{HEAD}$。Insert 操作指定已经存在的 anchor,并创建全局唯一、全序可比较的 ID,例如 $(\text{logical counter…”
形式陈述 ​
把操作视为唯一事件。关系
对操作型 CRDT,这条性质常通过 causal broadcast 实现:消息携带向量时钟或依赖摘要;接收端只有在本地版本支配全部依赖时才执行,否则进入缓冲。交付谓词必须与持久状态绑定,副本崩溃后不能忘掉已执行前驱却保留其后继。
因果顺序、eventual delivery 与 multiplicity 是三条正交合同。因果广播可以永远缓冲一个缺失前驱而不违反安全顺序,却违反最终交付;它也可能重复送达同一消息而保持相对顺序,却让非幂等 effector 执行两次。完整 CmRDT 定理仍需可靠性与恰一次或去重。
因果关系是偏序,不是全局总序。协议无需让无通信关系的两个副本就并发事件达成先后共识;数据类型通过并发 effectors 可交换来吸收这种自由。
逐发送者 FIFO 只是必要片段,并不足以覆盖跨来源的因果链。若 A 的事件
直觉
“我删除了刚才看到的添加”包含一条语义依赖:远端若还没见 add,就无法正确解释 remove 指向哪次添加。因果交付让效果算子在其前提已成立后运行。并发 add 没有被 remove 观察到,不属于前提,因而可以在 remove 前后任意出现并按冲突规则保留。
依赖摘要像一张待办清单,而非物理时间戳。向量分量说明每个来源至少应交付到哪一序号;本地缺一项就等待或拉取。墙钟即使完全同步,也不能仅凭时间判断某操作是否真的观察过另一操作。
因果交付会形成 head-of-line blocking:一个丢失前驱可挡住后继。实现要补发依赖、限制缓冲并处理永久故障,但不能为降低延迟直接跳过前驱后仍声称相同语义。
例子与边界
A 执行
C 若先执行 remove,而本地尚无
与此同时 D 未见 A 的 add,独立产生
若网络把 B 的 remove 重复两次,删除同一 dot 的集合操作是幂等的;若消息是整数 increment,重复便不安全。这个差异来自 effector 代数,不来自因果时钟。若 add 永久丢失,remove 会一直缓冲;严格保持顺序没有满足 eventual delivery,系统需重传前驱或明确宣布源故障后的处理规则。
推论与应用
因果交付可由发送方附完整 vector、稀疏 dependency set 或按会话维护的 causal token 实现。压缩摘要若遗漏真实依赖,会导致安全违规;保守地多报依赖只会增加等待,却可能造成可用性问题。交付完成最好指 effector 已进入可恢复状态,而非只从网络队列取出。
RGA 等序列 CRDT 借它确保 insert 的 anchor 在子节点之前存在;pure op-based CRDT 还可用因果稳定性判断某事件不会再遇到并发前驱。跨数据中心部署必须说明成员变化如何映射时钟分量,否则重用 actor ID 会让新事件被误判为旧前驱。缓冲上限若会丢弃依赖消息,也必须有状态修复路径。
参考资料
- Kenneth Birman, André Schiper, and Pat Stephenson, “Lightweight Causal and Atomic Group Multicast,” ACM Transactions on Computer Systems 9(3), 1991, pp. 272–314.
- Marc Shapiro et al., “A Comprehensive Study of Convergent and Commutative Replicated Data Types,” INRIA RR-7506, 2011, Sec. 2.4.
- Carlos Baquero, Paulo Sérgio Almeida, and Ali Shoker, “Making Operation-Based CRDTs Operation-Based,” DAIS 2014, pp. 126–140.