在多人实时协作应用中,如文档编辑或投票系统,CRDT(无冲突复制数据类型)通过数学性质确保副本间最终一致性,无需中心协调,支持离线操作与高可用。核心在于设计单调合并操作(如 max 或 union),让状态形成半格结构,实现交换、结合与幂等。Ian Duncan 的 CRDT 词典详细阐述了从 G-Counter 到 OR-Set 的权衡,该文聚焦工程实践:LWW 用于文本寄存器、PN-Counter 处理投票计数、OR-Set 带墓碑的集合操作,并对比 grow-only 与 pruning 策略。
LWW 寄存器:文本协作的简单方案
LWW(Last Writer Wins,最后写入胜出)寄存器适合多人编辑共享文本字段,如用户名或配置值,每个更新携带时间戳,合并取最新者。实现上,状态为 {value: string, timestamp: (wall_time, replica_id)},合并函数比较时间戳,平局用 replica_id 决胜。
工程要点:时间戳依赖混合逻辑时钟(HLC),融合物理时钟与 Lamport 时钟,避免 skew 达 100ms 以内。参数设置:replica_id 用 64-bit UUID,高 32-bit 编码时钟偏差阈值 10ms;更新频率限 1s/字段,避免抖动。落地清单:
- 初始化:timestamp = (0, 0),value = ""。
- 更新:生成 HLC t,若 t > current.timestamp,则覆盖。
- 合并:max(t1, t2),平局选 min(replica_id)。
- 回滚阈值:若 skew > 50ms,fallback 到 MV-Register 保留多值。
风险:并发更新丢失(仅保留一者),钟 skew 导致“幽灵”覆盖。Akka 文档中 LWWRegister 即为此例,适用于低冲突文本场景。
PN-Counter:投票计数的可靠选择
PN-Counter(Positive-Negative Counter)扩展 G-Counter,支持投票增减:维护 P(正增)和 N(负减)两张 per-replica 映射,value = sum(P) - sum(N),合并 per-replica 取 max。
多人投票中,用户 A/B 并发 +1/-1,最终收敛正确总和。工程参数:replica 限 1000(>则分片),P/N 用 uint64 防溢出;增量步长 1,合并批次 64。落地清单:
- 初始化:P = {}, N = {}。
- 投票 +1:P[replica] += 1。
- 投票 -1:N[replica] += 1。
- 合并:∀r, P[r] = max(P1[r], P2[r])。
- 监控:负值警报阈值 0.1%,GC 闲置 replica > 7 天。
证据:Redis CRDT 模块中 PN-Counter 用于点赞,合并无锁高吞吐。该结构空间 O(replicas),投票峰值 10k/s 时延迟 <5ms。
OR-Set:带墓碑的集合删除与 GC
OR-Set(Observed-Remove Set)支持添加/删除/重加:元素绑唯一 tag(replica_id:seq),添加生新 tag,删除移除观察到的 tag,元素存活若 tag 非空。墓碑即已删 tag 保留,用于防“僵尸复活”。
多人协作如购物车,A 添加 X(tag1),B 删除(观察 tag1),C 并发添加(tag2),最终保留 tag2。工程参数:tag 用 (u64 replica, u64 seq),GC 阈值 tombstone 比率 >20% 时触发;seq 回绕限 2^32。落地清单:
- 添加:tags.add(new_tag)。
- 删除:tags -= observed_tags。
- 合并:union(tags1, tags2)。
- GC:若 ∀replica 确认 seen_version > tag_birth,移除墓碑;频率 1h,安全窗 24h。
- 回滚:tombstone 堆积 >1M,强制全量快照。
引用 Shapiro 论文:“OR-Set 通过 tag 观察删除,确保添加优先于并发删除。” 空间 O(active + tombstones),GC 后 bounded。
Grow-Only vs Pruning:内存与一致性权衡
Grow-Only 如 G-Set/OR-Set 无删(union 合并),简单 O(1) 添加,但内存无界(活跃元素 + 历史 tag 累积),适合日志/指标(e.g. 点赞集)。Pruning 如 LWW/OR 带 GC,删除物理移除或墓碑超时清空,内存 bounded,但合并成本高(tag 比较 O(tags)),一致性需 causal 交付。
权衡表格:
| 策略 |
内存 |
合并延迟 |
适用场景 |
参数 |
| Grow-Only |
无界 O(n) |
低 O(1) |
追加日志、计数 |
无 GC |
| Pruning |
有界 O(k) |
中 O(t) |
协作编辑、购物车 |
GC 阈值 20%、窗 24h |
实时协作中,grow-only 初快但 OOM 风险高;pruning 稳但 GC 抖动(暂停 100ms)。建议:活跃用户 <100 用 grow-only,>1000 强制 pruning + delta-state 传增量。
落地参数与监控清单
- 全局:replica 限 4096,HLC skew 阈值 20ms,回滚到中心 Raft。
- LWW:字段 TTL 30min,冲突率 >5% 告警。
- PN:溢出阈值 2^60,负值率 >1% 排查。
- OR:tag/元素 <64,GC 周期 1h,tombstone 比率监控。
- 监控指标:merge_latency p99<50ms、tombstone_ratio<15%、gc_pause<200ms、convergence_time<5s、mem_growth_rate<1%/h。
- 部署:WebSocket 心跳 30s,delta 批次 100 ops;测试:Jepsen 模拟分区/并发。
资料来源:Ian Duncan《CRDT 词典》(https://www.iankduncan.com/engineering/2025-11-27-crdt-dictionary);CRDT 官网(https://crdt.tech/);Shapiro 等 CRDT 论文。