异步请求乱序时的同步变更追踪算法/方法咨询(MERN栈)
不使用WebSocket的处理方法
服务器管控的版本号方案:后端给每个文档维护一个自增的版本号,前端每次提交变更时,必须带上自己本地记录的最新版本号。后端收到请求后,先对比这个版本号和服务器当前的版本号:如果匹配,就执行变更并把版本号+1;如果不匹配,直接返回冲突提示。前端收到冲突后,先拉取服务器的最新文档版本,合并本地未同步的变更,再重新提交。这个方案完全不需要信任客户端,版本号由服务器说了算,从根源上解决乱序问题。
原子操作与OT算法:把文本的每个变更拆成原子操作(比如「在位置5插入字符'A'」「删除位置3开始的2个字符」),后端维护文档的完整操作日志。前端提交操作时,带上自己已经同步到的最后一个操作ID。后端收到后,检查这个ID之后有没有新的操作:如果没有,就把当前操作追加到日志;如果有,就用操作转换(OT)算法调整当前操作的位置和内容,和已有的新操作兼容后再应用到文档上。这种方法是主流协作工具的核心逻辑,能在保证顺序的同时,让多人编辑的冲突降到最低。
本地请求队列+幂等处理:前端本地维护一个待发送的请求队列,每次只发送队列里的第一个请求,等收到后端的成功响应后,再发送下一个。同时给每个请求生成唯一的客户端ID,后端处理前先检查这个ID是否已经被处理过,避免重复执行。这种方法严格保证请求顺序,但会稍微降低实时性,适合对操作顺序要求极高的场景。
WebSocket的作用说明
WebSocket是双向长连接,基于TCP协议,天然保证消息的传输顺序。一旦前后端建立连接,所有操作消息都会通过这个连接按顺序发送,服务器也会按接收顺序处理,从根本上避免了HTTP请求的乱序问题。而且WebSocket的延迟比HTTP请求低很多,更适合实时协作场景——后端处理完一个操作后,还能立刻把变更广播给所有在线用户,同步效率更高。不过需要额外处理连接断开重连的情况,比如重连后拉取断开期间的操作日志,补全本地数据。
内容的提问来源于stack exchange,提问作者MikeZe

