Workerman不能直接解决冲突,因其仅负责连接管理与消息转发,缺乏文档状态模型、操作序列化规则及合并策略,需自行实现OT或CRDT算法来保障多用户编辑一致性。

Workerman 本身不提供文档冲突合并逻辑,它只负责把操作广播出去;真正的合并必须由客户端或服务端基于 OT 或 CRDT 算法实现,否则多人同时改同一段落必然丢数据。
为什么 Workerman 不能直接解决冲突?
Workerman 是一个 PHP socket 服务器框架,核心能力是连接管理与消息转发。它没有内置的文档状态模型、操作序列化规则或合并策略——这些都得你自己补全。
-
onMessage回调里收到的只是原始操作(比如{"op": "insert", "pos": 12, "text": "hello"}),不是带上下文版本号的可合并操作 - 多个用户发来的操作到达顺序可能乱序(尤其在网络抖动时),
onMessage不保证 FIFO,更不保证因果顺序 - Workerman 不保存文档快照,也不维护每个客户端的本地状态,无法做三向合并(base/head/remote)
必须自己实现的操作建模与广播协议
要在 Workerman 上跑通协同编辑,第一步是定义可交换、可变换、可组合的操作类型,例如:
- 文本插入:
{"type": "insert", "pos": 5, "text": "x", "clientId": "u1", "seq": 12} - 文本删除:
{"type": "delete", "pos": 5, "len": 1, "clientId": "u2", "seq": 7} - 格式应用:
{"type": "format", "range": [5,8], "style": "bold", "clientId": "u1", "seq": 13}
所有操作必须带 clientId 和单调递增的 seq,服务端需按 (clientId, seq) 去重并排序,再分发给其他客户端。否则两个 insert 操作会因顺序错乱而错位。
服务端必须加一层 OT 合并调度器
纯靠广播不行,得在 Workerman 的 onMessage 之后插入一个中间层:接收操作 → 校验合法性 → 转换为标准 OT 操作 → 应用到服务端权威副本 → 对其他客户端广播变换后的操作(transformed operation)。
- 不能直接转发原始操作,必须调用
transform(opA, opB)函数重新计算位置偏移 - 例如用户 A 在位置 10 插入 “a”,用户 B 在位置 10 删除 1 字符,服务端收到 B 的操作后,要先对 A 的未确认操作做
transform,再执行 B 的删除,最后把变换后的 A 操作发给 B 客户端 - 推荐用现成 OT 库如
ot.js或sharejs的 PHP 移植版,别手写transform函数——边界 case 极多,比如嵌套列表、表格跨行、光标在换行符前后等
客户端必须同步维护本地副本和 pending stack
Workerman 只管发消息,但客户端必须自己做三件事:
- 本地编辑时,把操作暂存进
pendingStack,不立即渲染,等服务端返回确认后再提交 - 收到服务端广播的操作时,先用本地
pendingStack中未确认的操作做transform,再应用到本地文档 - 每次渲染前,必须用当前服务端版本号比对本地缓存,避免“回滚式渲染”(即旧操作覆盖新状态)
漏掉任意一环,都会出现光标跳变、内容闪烁或静默丢失——这些都不是 Workerman 的问题,而是 OT 状态机没闭环。

















