IM 系统中,保证消息的可靠投递主要体现在两方面,一是消息的不丢失,二是消息的不重复。

一、消息不丢失

消息丢失的原因

首先看一下发送消息的流程,如下图所示:
消息。可以采取“时间戳比对”机制进行完整性检查。


(图片来源于即时消息技术剖析与实战第 04 讲)

用户 A 发出的消息,先到达IM服务端(步骤1),由服务端暂存(步骤2),成功后,服务端将成功的结果返回给用户A(步骤3),同时将消息推送给用户B(步骤4)。
在这个过程中,丢失消息有以下几种情况:
1)步骤 1 因为网络不通等原因导致用户A把消息发送到IM服务器失败;
2)步骤 2 IM服务器存储消息失败;
3)步骤 3 用户A在超时时间内未收到IM服务器返回的结果;
4)步骤 4 由于IM服务器断电等原因导致消息未能成功推送给用户B(但步骤 3 用户A可以收到IM服务器返回的响应成功结果);
5)步骤 4 消息成功推送给用户B的设备,但用户B的设备因为一些原因如设备写入本地DB失败等,也会导致消息丢失。
前三种情况,用户A将被提示消息发送失败;后两种情况,用户B未收到消息。

消息丢失的解决方案

大部分场景中,业务层ACK确认机制 + 消息重传机制 + 消息完整性检查,能解决消息丢失的问题。
1.业务层的ACK确认机制和重传机制

ACK是确认字符(Acknowledge character)的意思,TCP协议默认提供了ACK机制,如果接收方成功接收到数据,就会回复一个ACK数据,表示发送方发出的数据已确认接收无误,在“三次握手”、“四次挥手”中经常见到。
ACK确认机制:TCP传输时将每个字节的数据都进行编号,即序列号。TCP传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答,也就是发送ACK报文。这个ACK报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。这也是TCP传输可靠性的保证之一。
重传机制:发送方发送一部分数据后,都会等待接收方发送的ACK报文,并解析ACK报文,判断数据是否传输成功。发送方迟迟收不到ACK报文的原因可能有两个:
1)数据在传输过程中由于网络原因等直接全体丢包,接收方没有接收到;
2)接收方接收到了响应的数据,但是发送的ACK报文响应却由于网络原因丢包了。
超时重传机制就是发送方在发送完数据后等待一个时间,如果在超时时间内没有接收到ACK报文,就重新发送数据。如果是上述的第一个原因,接收方收到二次重发的数据后,便进行ACK应答。如果是第二个原因,接收方发现接收的数据已存在,就直接丢弃,仍旧发送ACK应答。

业务层的ACK确认机制参考了TCP的ACK确认机制,其策略是IM服务器在推送消息时,携带一个标识SID(安全标识符,类似TCP的sequenceId),推送出消息后会将当前消息添加到“待ACK消息列表”,客户端B成功接收完消息后,会给IM服务器回一个业务层的ACK包,包中携带有本条接收消息的SID,IM服务器接收后,会从“待ACK消息列表”记录中删除此条消息,本次推送才算真正结束。

业务层的消息重传机制也参考了TCP协议的重传机制,IM服务器的“等待ACK队列”一般会维护一个超时计时器,一定时间内如果没有收到用户B发回的ACK包,就从“等待ACK队列”中重新拉取并进行重推。

为什么有了TCP协议本身的ACK机制,还需要业务层的ACK机制?
这是因为TCP属于传输层,而IM服务属于应用层。TCP的ACK保证网络传输层的可靠性,即消息是否送达,但不能保证数据能够被应用层正确可靠处理;业务层ACK进行消息是否送达和是否正确处理的逻辑,达到不丢消息、消息不重复的目的。

2.时间戳比对检查消息完整性
在上面列举的丢失消息的第 4 种可能性中,如果步骤 4 IM服务器将消息推送出去后就宕机了,而这条消息又因为某些原因丢失了,服务器由于宕机无法触发重传机制,导致用户B收不到该消息。可以采取“时间戳比对”机制进行完整性检查。


(图片来源于即时消息技术剖析与实战第 04 讲)

时间戳比对过程如下:
1)IM服务器给用户B推送msg1,同时带上一个最新时间戳timestamp1。用户B收到msg1后,更新本地的时间戳为timestamp1;
2)IM服务器给用户B推送msg2,同时带上一个最新时间戳timestamp2。由于某种原因,用户B和IM服务器的连接断开,导致msg2没有成功推送到用户B;
3)用户B和IM服务器重新建立连接后,将本地的时间戳timestamp1发送给IM服务器,IM服务器将时间戳大于timestamp1的所有消息全部发送给用户B,同时带上时间戳timestamp2(这里假设时间戳大于timestamp1的消息只有msg2,如果有msg3、msg4等多条消息,应取最新消息的时间戳);
4)用户B收到msg2后,更新本地的时间戳为timestamp2。
通过这样的比对可以有效解决消息丢失的问题。但时间戳由于有时钟不同步、或者一个时间戳内多条消息的可能性,存在误差,因此可以使用全局的自增序列版本号来代替。

二、消息不重复

消息重复的原因

在上面列举的丢失消息的几种可能性中,第 3 种可能性存在一种场景,步骤 4 将消息成功推送给用户B,但步骤 3 因为某些原因导致超时、用户A收不到响应,这个时候会触发重传机制,用户A重新发送请求,用户B可能会收到重复消息。

消息重复的解决方案

IM服务器推送消息时,携带一个Sequence ID,这个Sequence ID在本次连接会话中唯一,同时针对同一条消息不变。当接收方接收到消息后,会根据这个Sequence ID来进行业务层的去重,可以有效地保证消息的不重复。

三、小结

通过业务层的ACK机制、重传机制和完整性检查,可以有效解决推送过程中消息丢失的问题;
通过客户端的去重机制,可以有效解决消息重复的问题。

《即时消息技术剖析与实战》学习笔记4——IM系统如何保证消息的可靠性的更多相关文章

  1. 《即时消息技术剖析与实战》学习笔记5——IM系统如何保证消息的一致性

    一.什么是消息一致性 消息一致性指的是消息的时序一致性,即消息收发的一致性.如果不能保证时序一致性,就会造成聊天语义不连贯,引起误会. 对于点对点的聊天场景,时序一致性保证接收方的接收顺序和发送方的发 ...

  2. 《即时消息技术剖析与实战》学习笔记6——IM系统如何保证消息的安全性

    在消息产生.流转的各个环节中,需要保证消息传输安全性.消息存储安全性.消息内容安全性. 一.消息传输安全性 消息传输的重要防范点有两个,一是访问入口安全,二是传输链路安全. 1.HttpDNS保证访问 ...

  3. 《即时消息技术剖析与实战》学习笔记3——IM系统如何保证消息的实时性

    IM 技术经历过几次迭代升级,如图所示: 从简单.低效的短轮询逐步升级到相对效率可控的长轮询: 全双工的 Websocket 彻底解决了服务端的推送问题: 基于 TCP 长连接衍生的 IM 协议,能够 ...

  4. 《即时消息技术剖析与实战》学习笔记1——IM系统的架构

    一.IM的应用场景 聊天.直播.在线客服.物联网等所有需要实时互动.高实时性的场景,都需要应用到 IM 技术.

  5. 《即时消息技术剖析与实战》学习笔记12——IM系统如何提升图片、音视频消息发送、浏览的体验

    IM系统如何提升用户发送.浏览图片和音视频消息的体验呢?一是保证图片.音视频消息发送得又快又稳,二是保证用户浏览播放图片.音视频消息时流畅不卡顿. 一.提升用户发送图片.音视频的体验 1. 多上传接入 ...

  6. 《即时消息技术剖析与实战》学习笔记11——IM系统如何保证服务高可用:流量控制和熔断机制

    IM 系统的不可用主要有以下两个原因: 一是无法预测突发流量,即使进行了服务拆分.自动扩容,但流量增长过快时,服务已经不可用了: 二是业务中依赖的这些接口.资源不可用或变慢时,比如发消息可能需要依赖& ...

  7. 《即时消息技术剖析与实战》学习笔记7——IM系统的消息未读

    一.什么是消息未读 消息未读包括会话未读和总未读.前者指的是当前用户和某一聊天方的未读消息数,后者指的是当前用户的所有未读消息数,也就是所有会话未读的和.比如用户A收到用户B的2条消息,还收到用户C的 ...

  8. 《即时消息技术剖析与实战》学习笔记8——IM系统如何保证长连接的可用性:心跳机制

    假设有以下突发意外情况: 用户进入信号不好的地方,手机没有网络信号了 上网的路由器突然掉线了 这个时候,比如微信发消息,消息就会转圈圈,甚至变成红色叹号-- 上面情况都会导致"长连接&quo ...

  9. 《即时消息技术剖析与实战》学习笔记9——IM系统如何支持消息的多终端漫游

    一.什么是多终端漫游 多终端漫游是指:用户在任意一个设备登录后,都能获取到历史的聊天记录.如:QQ 默认漫游 7 天的聊天记录,开通 VIP 会员可漫游 30 天,开通 SVIP 会员可漫游 2 年. ...

随机推荐

  1. 自定义ItemToggleView

    极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...

  2. UEM“探针”技术及用户体验管理

    随着互联网产品越来越多,用户群体越来越庞大以及用户品位的多样性增加,我们会发现这样的一个规律,就是相同类型的产品,比如播放器中的QQ影音和暴风影音,再比如小游戏平台中的腾讯游戏和联众等等,他们的功能是 ...

  3. RBF神经网络

    RBF神经网络 RBF神经网络通常只有三层,即输入层.中间层和输出层.其中中间层主要计算输入x和样本矢量c(记忆样本)之间的欧式距离的Radial Basis Function (RBF)的值,输出层 ...

  4. java学习-NIO(二)Buffer

    当我们需要与 NIO Channel 进行交互时, 我们就需要使用到 NIO Buffer, 即数据从 Buffer读取到 Channel 中, 并且从 Channel 中写入到 Buffer 中.缓 ...

  5. 【Kubernetes 系列二】从虚拟机讲到 Kubernetes 架构

    目录 什么是虚拟机? 什么是容器? Docker Kubernetes 架构 Kubernetes 对象 基础设施抽象 在认识 Kubernetes 之前,我们需了解下容器,在了解容器之前,我们得先知 ...

  6. Opengl_入门学习分享和记录_番外篇01(MacOS上如何在Xcode 开始编辑OpenGL)

    写在前面的废话: 哈哈 ,我可真是勤勉呢,今天又来更新了,这篇文章需要大家接着昨天的番外篇00一起食用! 正文开始: 话不多说,先看代码. 这里主要全是使用的glfwwindowhint 这个函数,他 ...

  7. JavaMail的简单使用(自测可以发邮件)

    在很多项目中我们都会遇到发送邮件的功能,发送邮件其实还是很实用的,正好今天做项目需要实现,现在来简单的整理一下发送邮件的实现. 建立邮件与服务器之间的会话 Properties props = new ...

  8. Servlet生成验证码并进行账号密码和验证码的验证登陆!

    前言: 人不是生来就懂事的,在编程的世界也是一样,想想在大一的时候我还是那个连输出Hello World!都不会的小孩子是,现在我已经可以编出属于我自己的小程序了.编程其实并不可怕,可怕的是你不去编. ...

  9. LoRaWAN Server开源项目部署

    1,安装MQTT broker,Redis,PostgreSQL sudo apt install mosquitto mosquitto-clients redis-server redis-too ...

  10. JavaScript浮点数运算的精度问题

    之前在做浮点数计算时,偶然发现计算结果有误差,度娘了解了下,补充整理了下. 误差是什么样子的呢?举例 console.log(0.1+0.2); // 0.30000000000000004 事实上在 ...