Convergence Is Not Enough:合并为何失效?

Convergence Is Not Enough:合并为何失效?

在 Livelymerge 项目中,Dan Ingalls、Peter Van Hardenberg 和我(Alex Warth)试图将 Automerge 用于合并运行中程序的堆内存。虽然 Automerge 能保证多客户端最终状态一致,但我们发现这种收敛并不足以维护程序不变量。通过一个链表合并的实例,我们看到并发修改可能导致链表截断或形成死循环。问题在于 Automerge 合并的是写操作而非用户意图,导致跨对象的约束(如双向链表、树结构)被破坏。我们正探索通过定义 merge-aware datatypes,让合并操作在更高层级的抽象上执行,以在保持收敛的同时尊重数据结构的完整性。

合并重现的是操作的效果,而非用户的意图。
  1. wim

    我们正在构建一个多人协作 IDE [1],不过它是面向文档和规划场景的,要求文档必须是树形或图结构(以支持大纲、引用、转录等功能)。

    我们不能无条件地重放任意类型的操作进行合并,因为这可能会导致树形结构出现环。就像链表一样,某些操作对离线客户端本地而言可能是有效的,但在全局收敛后的顺序中却无效。

    我们的同步引擎区分不同类型的操作:无条件操作和受保护操作。

    无条件操作不能违反结构或数据模型不变性。例如 SetCompleted(task_guid, true)。简单的最后写入者胜(last-writer-wins)。

    受保护操作可以修改拓扑结构,比如 InsertMove(node_guid, parent_guid, after_guid)。这些操作会针对当前状态进行检查,而不是针对创建时的状态。在重放过程中,我们首先回滚乐观的本地操作,然后按顺序重放传入的规范操作。每个操作的 mutator 函数在应用前会验证当前状态,如果会违反某个条件(例如因为另一个客户端在此期间执行了另一次移动而导致产生环),则该操作会被确定性拒绝。在我们的案例中,还有一个权威服务器,因此我们也可以将相同的受保护操作用于数据结构之外的条件,比如权限。例如,AddUser(workspace_guid, user_guid) 的 mutator 函数可以先检查权限状态。

    [1] https://thymer.com

  2. alexisread

    关于格类型(lattice types)的相关论文(BloomL):

    https://dsf.berkeley.edu/papers/UCB-lattice-tr.pdf

    此外,你还需要一个因果寄存器(每键 Merkle 时钟)来对并发编辑进行排序,而不是直接丢弃其中一个。

    最后,你很可能需要一个 Pijul 风格的 VCS 来处理语义合并。

  3. Animats

    这显然是基于 Automerge [1] 的。听起来是个非常好的主意。这个主意足够好,能用来同步 MMO 游戏的客户端和服务器吗?

    论文是 2012 年的,Automerge 网站最后一次更新是在 2025 年。为什么这东西还没普及到 everywhere?

    [1] https://automerge.org/

同日更多故事

2026-08-03