<!-- title: 各改各的终归一致：CRDT合并内核拆解 -->
<!-- domain: programming -->
<!-- video: https://www.youtube.com/watch?v=x7drE24geUw -->

# 各改各的终归一致：CRDT合并内核拆解

## 导语：为什么你和同事同时改一份文档，最后不会"打架"？

设想一个再普通不过的场景：你正和三位同事协作编辑同一份设计稿，你拖动一个图层的颜色，A同事同时在移动它的位置，B同事此刻还断着网——他在高铁上继续修改。几分钟后B重新联网，所有人的改动竟然奇迹般地全部保留、互不覆盖，文档最终归于同一个确定的状态。

这件事之所以"奇迹"，是因为在分布式系统里，"多个副本各自修改、互不通信，最后还能合而为一"听起来就像在违反物理定律。让它成立的，是一类被称为 **CRDT（Conflict-free Replicated Data Type，无冲突复制数据类型）** 的数据结构。而如果要挑一个把这件事讲到骨头里的视频，非 Martin Kleppmann 的演讲《CRDTs: The Hard Parts》莫属——Kleppmann 是被程序员奉为"分布式圣经"的《Designing Data-Intensive Applications》（DDIA）的作者。

这篇解读要解决的问题是：CRDT 究竟靠什么数学魔法让"各改各的"也能收敛？为什么 Kleppmann 说 CRDT"很容易实现得很烂"？以及——它和你日常用的 Figma、Google Docs、以及 5G 核心网里的分布式数据，到底有什么关系。

## 视频背景卡片

| 项目 | 内容 |
|------|------|
| 视频标题 | CRDTs: The Hard Parts |
| 讲者 | Martin Kleppmann（剑桥大学副教授，《DDIA》作者） |
| 频道 | Martin Kleppmann — Talks（Hydra 分布式计算大会 2020） |
| 时长 | 约 52 分钟 |
| 影响力 | 分布式系统社区长期被反复引用的标杆级长青演讲，数十万次播放 |
| 核心主题 | CRDT 表面原理易懂，但"水面之下"藏着大量实现难题 |

## 核心内容拆解

### 要点一：CRDT 是为"乐观复制"而生的自动调停者

视频开篇就给 CRDT 划定了精确的活动范围。要理解 CRDT，得先理解分布式系统处理"同一份数据被多处同时修改"的两种截然相反的哲学——这一点在权威站点 crdt.tech 上讲得最清楚。

第一种叫**强一致复制（Strongly consistent replication）**：副本之间必须先"协商"达成共识，才能确认一次修改。这种方式能保证最强的正确性（可串行化事务、线性一致性），但代价沉重——必须等待协调完成，性能被拖累；更致命的是，**CAP 定理**告诉我们：当某个副本因为网络分区或离线而与系统失联时，它根本无法进行任何数据修改。

第二种叫**乐观复制（Optimistic replication）**：用户可以在任意副本上独立修改数据，哪怕这个副本处于离线、断网状态。这条路把性能和可用性拉满，但必然产生**冲突（conflict）**——多个人同时改了同一处，等副本重新通信时，冲突必须被解决。

> CRDT 正是为乐观复制系统服务的，它专门负责"自动解决冲突"。无论各副本做了什么修改，数据都能被合并成一个一致的状态，而且这个合并由 CRDT 自动完成，不需要任何特殊的冲突解决代码，也不需要人工干预。

（**延伸分析**）这条定义里最值钱的一个词是"自动"。传统分布式数据库让你写一大堆 if-else 去判断冲突怎么办；CRDT 把冲突解决策略"焊死"进数据结构本身。你只管改，合并不需要你操心。这是 CRDT 最反直觉也最优雅的地方——它用数学的确定性，换掉了工程的不确定性。

### 要点二：CRDT 的三道数学护身符——交换、结合、幂等

Kleppmann 反复强调：CRDT 能保证 **最终一致性（eventual consistency）**——只要不再有新更新，所有副本最终都会看到同一个结果。但"最终"凭什么成立？答案藏在三条看似枯燥的代数性质里，这是整个 CRDT 大厦的地基（**延伸分析**）：

1. **交换律（Commutative）**：合并的顺序不影响结果。先合并 A 再合并 B，等于先合并 B 再合并 A。
2. **结合律（Associative）**：合并的分组不影响结果。(A⊕B)⊕C = A⊕(B⊕C)。
3. **幂等性（Idempotent）**：把同一个更新合并两次，等于合并一次。A⊕A = A。

只要合并算子 ⊕ 同时满足这三条，就构成一个**半格（semilattice / join-semilattice）**。在半格里，无论消息以什么顺序到达、到达几次、丢没丢重不重传，所有副本的状态都只会沿着格"单调上升"，最终必然收敛到同一个"上确界"（least upper bound）。

> 这就是为什么 CRDT 不需要协调、不怕乱序、不怕重复——因为它从一开始就**不在乎顺序**。

（**延伸分析**）注意这三条性质其实是在给分布式系统"卸担子"：可靠 causal 广播、消息去重、全局排序这些昂贵的基础设施，对 state-based CRDT 都不是必需的。这正是 CRDT 与 Paxos/Raft 这类共识算法的本质区别——共识算法花大力气"统一口径"，CRDT 干脆承认"口径永远不统一，但结果一定一样"。

### 要点三：两大实现流派——传状态 vs 传操作

CRDT 在工程上分裂成两个家族，Kleppmann 在视频中都有涉及。

**State-based（基于状态，又叫 CvRDT / 收敛型）**：每个副本把自己的**完整状态**广播出去，接收方用一个合并函数把两边状态融合。合并函数必须是上面说的那个半格 join。优点是容错——丢包重传无所谓，幂等；缺点是状态越大、广播越胖（后来用"状态压缩/δ-CRDT"缓解）。

**Operation-based（基于操作，又叫 CmRDT / 交换型）**：副本之间不传状态，只传**操作（operation）**。它要求底层提供一个**可靠的因果广播（reliable causal broadcast）**通道：消息不丢、不重复、且因果有序。在满足这个前提下，只要操作本身满足交换律，合并就能正确。

（**延伸分析**）两者的取舍很像通信工程里"传整个文件 vs 传增量 diff"。CvRDT 像"全量同步"，简单粗暴费带宽；CmRDT 像"增量同步"，省带宽但要求传输层更可靠。在 5G 核心网里，网元之间做配置/状态同步时也常面临同样的"全量 vs 增量"抉择，背后的权衡逻辑完全一致。

### 要点四：CRDT 的乐高积木——Counter、Register、Set

视频没有停留在抽象数学，而是落到几个最基础的"积木"数据类型。这些是构建复杂 CRDT 的原子，也是理解 CRDT 思路最快的方式：

- **G-Counter（Grow-only Counter，只增计数器）**：每个副本维护自己的一个计数子项，合并时取各副本对应位置的最大值，最终值是所有子项之和。因为只能增，天然满足三条性质。
- **PN-Counter（Positive-Negative Counter）**：两个 G-Counter 拼起来，一个记增、一个记减，从而支持"减法"——这是计数器支持递减的标准套路。
- **LWW-Register（Last-Writer-Wins Register，后写覆盖寄存器）**：每个值带一个时间戳和一个 peer ID，合并时取时间戳大的；时间戳相同就用 peer ID 打破平局。
- **OR-Set（Observed-Remove Set，观察-删除集合）**：每次 add 带一个唯一标签，remove 时把"当时观察到的所有标签"记进墓碑集合，从而避免"我先删、你后加，结果被误删"的经典冲突。

> Figma 的博客里讲得非常直白：它用 LWW-Register 来同步"对象属性"——两个客户端改同一个对象的不同属性不会冲突，改同一属性就让服务器定谁后到谁赢；它用类似 last-writer-wins set 的思路来管理"对象是否存在"。

（**延伸分析**）这套积木的思想极简：**把"容易冲突的操作"翻译成"天然无冲突的数据表示"**。计数难，就拆成每个副本独立计数再相加；删除难，就不真删、改记墓碑。这与通信里"用冗余换确定性"的工程哲学一脉相承。

### 要点五：真正的"硬骨头"——序列/列表 CRDT（文本协作编辑）

到这里都还是"入门甜点"，视频标题里的 **The Hard Parts（硬骨头）**真正从"文本/列表编辑"开始。这也是 Kleppmann 全场最精彩的部分。

问题看似简单：两个人在协作文档里插入文字。A 在第 5 个位置插入了"Hello"，B 同时在第 5 个位置插入了"World"。麻烦在于——"位置"是会漂移的。当 A 的插入还没到达 B 时，B 眼里的"第 5 位"和 A 眼里的"第 5 位"已经指代不同的物理位置了。如果天真地用"位置下标"来描述插入，合并后文字会错乱。

> 为此，研究者发明了一整套**序列 CRDT** 算法：WOOT、Treedoc、Logoot、LSEQ、RGA。它们的共同思路是——放弃用"脆弱的整数下标"定位，改用"唯一标识符"来定位每个字符，让插入位置不依赖当下文档状态。

但 Kleppmann 用自己团队的研究戳破了"乐观"：他在 PaPoC 2019 发表的论文揭示了 **交错异常（Interleaving Anomaly）**——许多已发表的序列 CRDT 算法，在特定并发场景下，会把两个人分别打入的字符**错误地交错穿插**，产出谁都不想要的乱码（比如 "HeWlolorld"）。这类算法"很容易实现得很烂"，而且"许多已发表的算法都有异常，导致它们在某些情况下表现得很奇怪"。

（**延伸分析**）这段是整场演讲最该被记住的警示：CRDT 的"无冲突"只在数学层成立，具体算法在真实并发下的**人类可读性**是另一回事。这也是为什么 Kleppmann 的团队后来用 OpSets（操作集合）给 RGA 做了形式化证明，证明 RGA 确实不会交错——证明一个数据结构"正确"，本身就是 PhD 级别的难活。

### 要点六：删除是最大的坑——墓碑与元数据爆炸

序列 CRDT 还埋着一个更深的雷：**你根本不能真正删除任何东西**。原因听起来反直觉——

假设 A 删掉了第 5 个字符，而 B 此时还不知道删除这件事，正基于"字符还在"的状态插入一个新字符。如果 A 真把那个字符从记录里抹掉，B 的插入就失去了参照物，合并必然出错。所以 CRDT 的删除，本质上是一种"**软删除（tombstone，墓碑）**"——被删的字符只是被标记为"看不见"，但它的标识符、时间戳必须永久保留，好让后来的并发操作能正确定位。

> 后果就是：**元数据（metadata）会无节制地膨胀**。一份编辑了上万次的文档，墓碑会堆积如山，简单实现的 CRDT"性能极差"，而让它性能好"非常具有挑战性"。

Kleppmann 给出的解法是他在 Automerge（最流行的 CRDT 库之一）上的研究：用**列式编码（columnar data encoding）**和**二进制数据格式**来压缩元数据开销。这正是他在参考文献里列出的 "Experiment: columnar data encoding for Automerge" 和 "Automerge binary data format"。

（**延伸分析**）这条对工程实践的冲击极大：选 CRDT 不是选了就"高可用"，而是用**无限的内存增长**换取**无需协调的合并**。长生命周期、高频编辑的场景（比如一个用了三年的协作文档）必须配套墓碑压缩/GC 策略，否则内存迟早爆炸。Figma 的做法更务实——删除对象时，被删对象的属性**不留在服务器**，而是塞进执行删除那个客户端的 undo buffer，由它自己负责恢复，从而让"长寿文档不会因为编辑而持续膨胀"。这是中央服务器架构才能享受的"作弊"特权。

### 要点七：被忽视了十年的"移动操作"

Kleppmann 在视频中点出一个曾被整个学术圈长期忽视的空白：**移动（Move）操作**。

绝大多数早期 CRDT 研究都聚焦在"增、删"，却很少严肃处理"把一个元素从 A 位置搬到 B 位置"这种最日常的操作。这在纯文本编辑里还能凑合（删了重加），但在**树形结构**（文件系统、设计图层级、思维导图）里，"移动一个节点"和"删除再新建"完全不是一回事——后者会丢失节点身份（identity），导致并发的其他修改全部失效。

> 为此 Kleppmann 团队发表了 "A highly-available move operation for replicated trees"（面向复制树的高可用移动操作），专门解决"移动 + 并发删除"交错时如何保持正确，这是分布式文件系统能用 CRDT 的前提。

（**延伸分析**）Figma 的工程笔记恰好印证了这个"移动有多难"：它把"父子关系"表示成"子节点上存一个指向父节点的链接"（而不是父节点存子节点列表），从而在 reparenting（重新指定父节点）时保持对象身份不变。但这就引入了新麻烦——**环（cycle）**：A 把 B 挪到自己下面、同时 B 把 A 挪到自己下面，就形成了环。Figma 的服务器会拒绝造成环的更新，客户端则在冲突时"暂时把这两个对象互相挂载并从树里摘出，直到服务器驳回"。Figma 还用 **分数索引（fractional indexing）**——用一个 0~1 之间的分数表示顺序，插入时取两邻居分数的平均值——来确定子节点排列。这套组合拳，就是 CRDT 思想在中心化产品里的"实用降维版"。

### 要点八：CRDT vs OT——为什么 Figma 和 Google Docs 走了不同的路

视频之外，最值得补的一笔是 **OT（Operational Transformation，操作转换）** 与 CRDT 的世纪对比，这也是 Figma 博客的核心叙事。

Google Docs 用的是 OT：所有操作流经一个**中央服务器**统一排序，服务器对并发操作做"转换"，让它们能正确叠加。OT 的致命伤在于**状态空间组合爆炸**——用论文原话说，"即使只处理 insert 和 delete 两种基本操作，形式化证明也极其复杂、极易出错"，"导致难以预见的复杂状态组合"。

Figma 当年评估后选择了**不走 OT、也不走"纯 CRDT"**，而是"**受 CRDT 启发的自研系统**"。理由很务实：Figma 是中心化的（有中央服务器当唯一裁判），可以名正言顺地砍掉 CRDT 为去中心化付出的性能/内存开销；而且 Figma 不是文本编辑器，不需要 OT 那套处理长文本的能力，"杀鸡焉用牛刀"。

> Figma 的核心结论之一非常发人深省：**"即使你不是在做去中心化系统，CRDT 文献同样大有可为。"** CRDT 是一套被深入研究过的、坚实的地基，理解它能帮你构建出正确的系统，然后你可以"根据应用需要放松掉其中一些要求"。

（**延伸分析**）这场对比的真正启示不是"谁赢谁输"，而是**先问清楚你的系统假设是什么**。需要去中心化/离线优先/P2P → CRDT；有强中心、追求极简 → 受 CRDT 启发但去繁就简；要强一致/可串行化事务 → 老老实实上共识算法。没有银弹，只有匹配场景的权衡。

## 知识结构图

```mermaid
graph TD
    A["CRDT 无冲突复制数据类型<br/>各副本独立修改，自动合并"] --> B["目标：乐观复制下自动解决冲突"]
    A --> C["数学地基：半格 join<br/>交换律 ∪ 结合律 ∪ 幂等性<br/>→ 最终一致性"]
    A --> D["两大实现流派"]
    D --> D1["State-based CvRDT<br/>广播完整状态<br/>容错好，状态胖"]
    D --> D2["Op-based CmRDT<br/>广播操作<br/>省带宽，需因果广播"]
    A --> E["基础积木"]
    E --> E1["G-Counter 只增计数"]
    E --> E2["PN-Counter 可减计数"]
    E --> E3["LWW-Register 后写覆盖"]
    E --> E4["OR-Set 加删集合+墓碑"]
    A --> F["The Hard Parts 硬骨头"]
    F --> F1["序列CRDT 文本协作<br/>WOOT/Treedoc/Logoot/LSEQ/RGA"]
    F --> F2["交错异常 Interleaving<br/>需形式化证明"]
    F --> F3["删除即墓碑<br/>元数据爆炸→列式压缩"]
    F --> F4["移动操作 Move<br/>CRDT树/分布式文件系统"]
    A --> G["工程对照"]
    G --> G1["OT 操作转换<br/>Google Docs 中心化"]
    G --> G2["受CRDT启发<br/>Figma 自研降维"]
```

## 实战启示：CRDT 对你到底意味着什么

**如果你是应用开发者**，最大的启示是——**别从零造 CRDT，直接用成熟库**。Kleppmann 全场演讲其实都在论证"CRDT 极易实现得很烂"，连顶会论文都会出交错异常。生产环境请直接上 **Automerge**（Kleppmann 本人参与，主打 local-first）或 **Yjs / Y-CRDT**（Kevin Jahns 出品，性能极佳，被 Notion、Atlassian 等大量采用）。它们已经替你趟过了墓碑压缩、交错证明、移动操作这些深坑。

**如果你在做协作/离线优先产品**，CRDT 是当前唯一能在"断网也能改、联网必合并"这件事上给出数学保证的方案。判断要不要用的标准很简单：你的用户是否需要**离线编辑后无缝合并**？是 → CRDT；只是"实时多人在同一服务器上编辑" → OT 或更简单的方案也够。

**如果你来自通信行业（这正是 51学通信 读者的主场）**，CRDT 的思想其实早已潜伏在你身边。5G 核心网里 **UDR（统一数据仓库）的多副本同步**、**UDM/UDR 的地理冗余**、网元之间状态数据的最终一致性，本质上都是"乐观复制 + 冲突调和"的问题域。当 NF（网络功能）跨数据中心、跨边缘部署时，强一致共识的开销会拖垮可用性，而 CRDT 式的"各副本独立演进、最终收敛"反而更贴合通信系统对**高可用**的执念。尤其在**边缘计算（MEC）**和**本地优先**趋势下，"断网也能写、联网自动合"正是 5G/6G 分布式数据架构的方向。理解 CRDT，等于掌握了评估这些分布式数据方案正确性的底层标尺。

一句话：CRDT 用"不在乎顺序"的数学，换来了"无需协调也能合一"的工程自由——它不是让你写更少的代码，而是让你**少写那些永远写不对的冲突处理代码**。

## 延伸学习路径

1. **crdt.tech**（https://crdt.tech/）——CRDT 社区的官方门户，最权威的入门定义、算法清单和库索引，读完它就有了正确的术语地基。
2. **《Designing Data-Intensive Applications》**（Martin Kleppmann 著）——第 5 章"复制"系统讲解了乐观复制、最终一致性与冲突处理，是理解 CRDT 出现动机的最佳背景读物。
3. **Automerge / Yjs**——两个最成熟的开源 CRDT 库。建议各跑一个 demo，亲手感受"断网编辑后合并"的丝滑，再回头看本视频会豁然开朗。
4. **"Local-first software" 论文**（Kleppmann 等，Onward! 2019）——CRDT 的"信仰宣言"，论述为何"数据该归用户所有、云只是同步工具"，直接对应当下 AI 本地化、数据主权的趋势。
5. **Figma 博客《How Figma's multiplayer technology works》**（Evan Wallace）——生产级中心化系统的"降维实战"，把 CRDT 思想与 OT 对比、分数索引、树 reparenting 讲得通透，是本视频最好的工程注脚。

## 一句话总结

CRDT 用"交换律+结合律+幂等"这三道数学护身符，把分布式世界里最令人头秃的"冲突解决"焊进了数据结构本身——让多个副本即使各改各的、断网离线，也终将归于同一个确定的未来。

## 参考来源

1. [CRDTs: The Hard Parts — Martin Kleppmann（Hydra 2020 演讲）](https://www.youtube.com/watch?v=x7drE24geUw) — 本次解读的核心视频
2. [About CRDTs · crdt.tech](https://crdt.tech/) — CRDT 社区官方门户，权威定义与乐观复制/强一致对比
3. [How Figma's multiplayer technology works — Figma Blog](https://www.figma.com/blog/how-figmas-multiplayer-technology-works/) — 生产级 CRDT 启发系统实战案例
4. [CRDTs: The Hard Parts — Martin Kleppmann's talks（演讲参考文献清单）](https://martin.kleppmann.com/2020/07/06/crdt-hard-parts-hydra.html) — 演讲引用的全部学术论文（Logoot/LSEQ/RGA/移动操作等）
> 本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵**爱卫生**（微信ID: gprshome201101）维护，聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。
> 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
### 完成摘要（What was done）

### 下一步计划（What's next）

- **优先级1**：如需我把本文转成 51学通信风格 PPT 或中文讲解视频，可直接用 `51xtx-ppt-writer` 或 `content-to-video` 技能生成。
- **优先级2**：可补充一份"5G 核心网 UDR 多副本同步 vs CRDT"的专题对照表，强化通信场景的落地价值。
- **优先级3**：CRDT 与共识算法（Raft/Paxos）的边界对比可作为下一篇延伸选题。

### 注意事项

- 因 YouTube 反爬与搜索后端额度限制，**视频播放量为定性描述（"数十万次级别、社区标杆演讲"）而非精确数字**，实际数字建议发布前人工核对一次。
- 文中算法名（WOOT/Treedoc/Logoot/LSEQ/RGA）、论文（Interleaving Anomaly、OpSets、Move operation、列式编码）均来自 Kleppmann 演讲页参考文献，可靠；Figma 实现细节（分数索引、树 reparenting、undo 策略）来自其官方博客。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
