知识卡片

多终端同步与传统IM投递的本质差异

普通读书笔记卡

内容

多终端同步是指用户在多个终端间切换时能获得一致性体验、不丢失上下文,如果多个终端同时在线还要做到实时同步——这个需求随着移动端独立应用和PC端富客户端化的普及而变得越来越重要,因为传统基于浏览器和HTTP协议的缓存规则机制在富客户端场景下失效了,客户端需要针对具体业务场景自己设计缓存,否则每次全量拉取会很浪费流量。要理解为什么多终端同步不能简单套用传统IM投递机制,得先理解传统IM投递机制本身的一条根本限制——SMC定理(Single-Message Communication)指出:任何端到端的消息传递协议,不可能做到消息既不丢失也不重复,传统IM要么接受消息丢失、要么接受确认重试带来的重复问题(可以在应用层做排重来缓解,但无法从根上消除)。用传统IM投递机制加历史记录也能凑出一种多终端同步(所有设备在线时直接投递,离线转在线时拉取历史记录补齐),但这样做有两个难点:一是”变更如何同步”——传统IM的消息是不可变对象,而群组列表、联系人列表这类数据是可变的,传统投递机制天生不知道该怎么处理”更新”和”删除”这类变更;二是投递确认机制的缺陷会导致一致性难以控制,一旦多个终端状态不一致,客户端没有自我修复的手段,只能靠特殊刷新机制让用户手动刷新。微信的SYNC协议(虽未完全公开)代表了另一种思路:把”消息投递”转换成”基于状态的同步”——通过服务器通知客户端有新变化、客户端按版本号做增量拉取,每个Folder的版本号严格有序递增,消息投递类似邮件、被送进每个人的收件箱、每投递一条消息版本号加一。这条从”投递(push新消息)”到”同步(拉取版本增量)”的范式转变,正是多终端同步问题相对传统IM投递机制的本质差异:投递关心的是”这条消息有没有送到”,同步关心的是”当前状态和服务器最新状态之间差了哪些版本”,后者天然具备可以自我对齐、自我修复的结构。

参考来源

- 位置:《高可用架构(第1卷)》第1章《高可用架构案例精选》"1.3 如何设计类似微信的多终端数据同步协议:Grouk实践分享"节,"1.3.2 多终端数据同步与传统消息投递协议的差异"(源文件:_epub-src/OEBPS/Text/Chapter1_3_3.xhtml) - 结论依据:原文引用SMC定理"任何端到端的消息传递协议,不可能做到消息既不丢失也不重复",并说明传统投递机制加历史记录方案的两个难点("变更如何同步?……投递确认机制的缺陷会造成一致性不好控制的情况"),再介绍微信SYNC协议"将消息投递转换为基于状态同步的协议",直接支撑本卡片结论。 - 原始内容:任何端到端的消息传递协议,不可能做到消息既不丢失也不重复……同步机制是通过服务器通知、客户端拉取机制实现的。IM协议投递的是新消息的通知,拉取是根据版本号增量同步,将消息投递转换为基于状态同步的协议。