如何读懂 CRDT 实时协作原理:Macro 的 Loro + Durable Objects 架构完整指南
如何读懂 CRDT 实时协作原理Macro 的 Loro Durable Objects 架构完整指南【免费下载链接】macroMacro is a unified workspace for teams: email, chat, docs, tasks, agents, calls, and CRM — -linked together with shared AI memory.项目地址: https://gitcode.com/GitHub_Trending/macro3/macro在团队协作工具 Macro 中邮件、文档、任务、CRM 和 AI Agent 共享同一个工作区多人甚至人 AI同时编辑时光标实时可见、内容零冲突合并——这正是CRDT 实时协作技术的落地。本文将带你剖析 Macro 如何基于 Loro CRDT 与 Cloudflare Durable Objects 构建这套同步引擎从客户端镜像到服务端房间模型完整看懂整条链路。什么是 CRDT实时协作的数学基础先说结论CRDTConflict-free Replicated Data Type无冲突复制数据类型让多台设备上的同一份数据各自独立修改再按任意顺序合并最终结果必然一致。这解决了实时协作里最经典的痛点传统方案痛点CRDT 的解法多人同时编辑后写覆盖先写每次修改被记录为操作Operation而非状态断网编辑丢失离线操作排队恢复后自动合并需要中心服务器裁决冲突合并算法天然幂等无需仲裁Macro 选择 loro-crdt 作为底层引擎——它是一个 Rust 内核、带 TypeScript/多语言绑定的现代 CRDT 库支持富文本、列表、Map 等协作数据结构并用**版本向量Version Vector**追踪每台设备的操作进度从而只传输对方缺少的增量。客户端架构Loro Mirror 双向同步层Macro 团队没有让业务代码直接操作 CRDT而是在 packages/loro-mirror/ 中封装了一层Loro Mirror——一个在应用状态与Loro 文档之间双向同步的状态管理层。用 Schema 声明协作结构开发者只需声明一份类型安全的 Schema就能把任意 React/Solid 风格的应用状态映射到 CRDT 容器上schema.String()/schema.Number()/schema.Boolean()—— 基础类型schema.LoroText()—— 支持字符级协作的富文本schema.LoroMap()/schema.LoroList()—— 对象与数组容器schema.Ignore()—— 仅本地、不参与的字段详细用法可参考 packages/loro-mirror/REFERENCE.md。最小化操作ID 选择器的妙用列表更新最容易刷屏——朴素做法是删掉整个列表再重建这会让同步流量爆炸。Loro Mirror 提供了ID 选择器idSelector声明列表时指定(item) item.idMirror 用 ID 而非下标追踪每一项更新状态时做智能 Diff只找出真正新增、删除、修改的条目重排序时生成轻量的move 操作而不是删除 重建这直接减少了需要跨网络同步的操作数是大型协作列表性能的关键。同步引擎双通道 快照的客户端大脑连接服务端的是 packages/collaboration/src/collab/ 中的同步引擎engine.ts它同时管理两条同步通道WAL 通道Write-Ahead Logwal.ts所有本地修改先落盘保证刷新/崩溃后操作不丢Live 通道source.ts通过 WebSocket 与服务端保持实时增量同步同时还有三个贴心设计每 5 秒向快照存储提交一次snapshot-store.ts加速下次冷启动加载Awareness 存在感知awareness.ts传输光标位置、在线状态等临时状态不进入版本历史本地 BroadcastChannel 广播chatter.ts同一浏览器的多个标签页之间免走网络、秒级互通服务端架构Durable Objects 房间模型这是整条链路最精彩的部分。Macro 的同步服务 services/sync-service/ 是一个 Cloudflare Worker用 Rustworker-rs编写核心类DocumentSyncSession定义在 durable_object.rs。每个文档 一个房间架构文档services/sync-service/README.md概括得非常清楚客户端通过 WebSocket 连接/document/:document_idWorker 检查该文档的 Durable Object 是否存在不存在就动态创建一个。每个 Durable Object 就是一个文档的房间。Durable Objects 的独特之处它既是计算节点内存中持有完整的 Loro 文档副本又是持久化存储操作历史存 SQLite配置见 wrangler.toml 中的new_sqlite_classes [DocumentSyncSession]。这意味着房间里的内存文档是所有连接者的单一事实来源客户端的操作先到房间、合并进文档再广播给房间内其他所有连接房间崩溃后从持久层重放操作即可无损恢复心跳保活对抗 10 秒内存驱逐一个工程细节值得注意Cloudflare 会在 Durable Object10 秒无活动时驱逐其内存状态——即使仍有 WebSocket 连接。而重新导入 Loro 快照的计算代价很高。Macro 的解法README 原文每 5 秒调度一个 alarm 心跳像防抖一样周期性踢一下房间阻止内存驱逐。心跳同时承担落盘职责——每次触发时生成新的 Loro 快照写入持久存储。快照 增量的冷启动策略新用户加入文档时房间执行经典的两段式交付从持久存储取最新快照完整状态 快照之后积压的操作增量一次发给客户端客户端用版本向量比对后只应用缺失部分快照除了存在 Durable Object 的 KV 里还会备份到R2 对象存储wrangler.toml 中的DOCUMENT_SNAPSHOT_BUCKET兼顾读写速度与数据冗余。传输协议与安全Bebop JWT最后补齐两个工程化细节Bebop 序列化客户端与服务端共用一份.bop模式定义packages/collaboration/bebop.json自动生成 Rust / TypeScript 双向绑定WebSocket 上传输紧凑的二进制帧而非 JSONJWT 鉴权document_storage_service为每份文档签发带权限的 JWT客户端通过查询参数传给 WebSocketsync-service 校验后才允许收/发操作durable_object.rs 中的AccessLevel还支持只读访问级别的精细控制为什么这套架构值得学习把全文浓缩成一张对照表关注点Macro 的选择价值冲突解决Loro CRDT 版本向量数学保证最终一致断网可离线应用集成Loro Mirror 双向同步 智能 Diff业务代码零感知流量最小化实时传输WebSocket Durable Objects 房间每文档单点扇出天然水平扩展持久化DO SQLite R2 快照双备份崩溃可恢复冷启动快保活策略5 秒 alarm 心跳廉价解决内存驱逐问题这套设计的更深层意义当 AI Agent 成为团队的新成员ai-peer.ts 中专门有人机协作的 peer 通道所有人与机器共享同一套 CRDT 同步语义——AI 改文档、你回退、AI 再修正全部无冲突收敛。这正是统一工作区邮件、聊天、文档、任务、CRM 全在一个协作平面里能够成立的技术底座。延伸阅读客户端协作运行时总览packages/collaboration/README.mdLoro Mirror API 参考packages/loro-mirror/REFERENCE.md同步服务端架构说明services/sync-service/README.md部署与存储绑定配置services/sync-service/wrangler.toml【免费下载链接】macroMacro is a unified workspace for teams: email, chat, docs, tasks, agents, calls, and CRM — -linked together with shared AI memory.项目地址: https://gitcode.com/GitHub_Trending/macro3/macro创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →