什么时候不要使用 CRDT
CRDT 在协作编辑与离线友好型应用中表现出色,但它并不能替代所有协调、事务或鉴权需求。以下指南帮助你识别 CRDT 不适合的场景,并考虑替代方案。
快速概览
CRDT 的特性是“合并”,而不是“拒绝”。只要操作发生,它就会被合并;这与需要在操作发生时就获得全局一致结论的场景相冲突:
- 强不变量:必须永远成立,例如余额 ≥ 0
- 排他所有权:某一资源只能有一个获胜者
为什么 CRDT 在这些场景会失效
- 合并是单调的:远端编辑到达时无法“回滚”
- 副本之间没有锁或事务
- 在节点之间执行“检查再写入”需要协调,而不仅仅是最终一致
常见问题场景
1)排他资源管理
多名用户同时预定同一会议室 / 时间。
// 仅采用 CRDT 模型时,合并后两个意图都存在
// 应用必须通过外部流程选择获胜者
book("A101@2pm", { by: "A" })
book("A101@2pm", { by: "B" })
// 同步后:两个条目并存 → 若无协调则违反不变量替代方案:
- 事务型权威(中心服务器或数据库)
- 分布式一致性协议(如 Raft / Paxos)保障所有权
- 混合模式:UI 草稿用 CRDT,最终确认由服务器裁决
2)金融交易
两个提款操作同时发生在 100 美元账户上。
// 每个客户端本地应用自己的提款
withdraw(60) // A
withdraw(60) // B
// 合并后,简单累加会导致透支替代方案:
- 在权威存储上执行 ACID 事务
- 单写者模型,由唯一节点负责校验命令
- 服务器端检查的事件溯源账本
其他不宜只靠 CRDT 的情况
- 唯一性约束(用户名、slug、每组 only-one 主记录)
- 必须在写入时立即执行的授权判断
- 全局不变量(引用完整性、跨文档求和等)
CRDT 适用良好的场景
当合并后的结果有意义,并且临时不一致可接受时,CRDT 大放异彩:
- ✅ 协作文本文档、列表、map、在线状态
- ✅ 评论、表情、草稿、批注
- ✅ 离线编辑,只要最终能够收敛即可