一个低成本确保 IM 消息时序的方法探讨
1、前言
IM 类系统中,都需要考虑消息时序问题,如果后发送的消息先显示,可能严重扰乱聊天消息所要表达的意义。
IM 系统中主要有两类消息:
单聊消息:两个人之间的聊天,需要确保发送方和接收方消息时序展示一致;
群聊消息:一群人在一起聊天,需要确保所有接收方消息顺序一致。
消息时序是分布式系统架构设计中非常难的问题,一个分布式的 IM 系统必须要解决这个问题。另一篇文章《如何保证 IM 实时消息的“时序性”与“一致性”?》更多详细地探讨了消息时序的问题,有兴趣的可以深入看看。作者的另一篇文章《一套海量在线用户的移动端 IM 架构设计实践分享(含详细图文)》也值得一看。
▼ 更多 IM 开发干货系列文章:
《IM 消息送达保证机制实现(一):保证在线实时消息的可靠投递》
《IM 消息送达保证机制实现(二):保证离线消息的可靠投递》
《如何保证 IM 实时消息的“时序性”与“一致性”?》
《IM 单聊和群聊中的在线状态同步应该用“推”还是“拉”?》
《IM 群聊消息如此复杂,如何保证不丢不重?》
《一种 Android 端 IM 智能心跳算法的设计与实现探讨(含样例代码)》
《移动端 IM 登录时拉取数据如何作到省流量?》
2、为什么会出现时序问题
1 时间不一致导致
IM 系统存在大量的客户端、IM 服务器集群、长连接接入层集群、短连接接入层集群、数据库集群,这些应用分布在不同的机器上,时间很可能不一致,时区也可能不一致。
2 网络传输导致
网络传输延迟不同。同一用户后发送的消息可能早与先发送的消息到达服务器;不同用户的发送的消息到达服务器的延时差异可能更大。如下图,msg1 先发送,msg2 后发送。由于网络原因,可能 msg2 先到达消息服务器:
3 服务集群时差导致
由于 IM 服务器分布式部署,不同的消息可能路由到不同的逻辑层处理。路由到不同 logic 的时延不同(尤其是跨机房),且不同 logic 之间存在微量时差。见下图所示。
4 消息处理速度不一致导致
服务器收到消息后,不同 logic,不同线程对消息的处理速度可能不同,导致投递消息的时序出现错乱。
3、低成本解决办法探讨
以下内容是成本较低的解决办法,在产品快速开发迭代的场景下能够求得质量和效率的平衡。
1 时间同步
确保服务器端各个服务器之间通过 NTP 协议实现时间同步,确保各个操作系统时区一致。NTP 协议基本可以保证各个服务器的时间误差在毫秒级,并且在误差较大时能够出发报警(感谢运维团队)。
2 单聊时序
单聊消息可能出现时序问题如下图:
用户 1 发送消息时,确保每条消息的 seq 号递增(如果系统重装,需要客户端将 seq 写成文件保存,重装后能够继续 seq 递增)。
消息发送到服务器后,因为网络及分布式原因,可能造成服务器接收消息时序错乱
服务器推送消息给用户 2,可能因为网络原因再次出现时序错乱。用户 2,需要根据 seq 对消息显示时序进行修正。
注:对于 seq 归 0 的情况(比如,记录 seq 的文件被删除),用户 2 需要结合 timestamp 时间及 seq,共同判断消息时序。
3 群聊消息
群聊不能再利用发送方的 seq 来保证时序,因为发送方不单点,时间也不一致。群聊消息以服务器收到发送消息的顺序为准,服务器为每条消息生成时间有序的 msgid,客户端以 msgid 大小顺序来排序即可。
以上是生产环境中的一些实践,该方法在较低成本下,确保了消息时序的一致性。
评论