《即时消息技术剖析与实战》学习笔记4——IM系统如何保证消息的可靠性
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系统如何保证消息的可靠性的更多相关文章
- 《即时消息技术剖析与实战》学习笔记5——IM系统如何保证消息的一致性
一.什么是消息一致性 消息一致性指的是消息的时序一致性,即消息收发的一致性.如果不能保证时序一致性,就会造成聊天语义不连贯,引起误会. 对于点对点的聊天场景,时序一致性保证接收方的接收顺序和发送方的发 ...
- 《即时消息技术剖析与实战》学习笔记6——IM系统如何保证消息的安全性
在消息产生.流转的各个环节中,需要保证消息传输安全性.消息存储安全性.消息内容安全性. 一.消息传输安全性 消息传输的重要防范点有两个,一是访问入口安全,二是传输链路安全. 1.HttpDNS保证访问 ...
- 《即时消息技术剖析与实战》学习笔记3——IM系统如何保证消息的实时性
IM 技术经历过几次迭代升级,如图所示: 从简单.低效的短轮询逐步升级到相对效率可控的长轮询: 全双工的 Websocket 彻底解决了服务端的推送问题: 基于 TCP 长连接衍生的 IM 协议,能够 ...
- 《即时消息技术剖析与实战》学习笔记1——IM系统的架构
一.IM的应用场景 聊天.直播.在线客服.物联网等所有需要实时互动.高实时性的场景,都需要应用到 IM 技术.
- 《即时消息技术剖析与实战》学习笔记12——IM系统如何提升图片、音视频消息发送、浏览的体验
IM系统如何提升用户发送.浏览图片和音视频消息的体验呢?一是保证图片.音视频消息发送得又快又稳,二是保证用户浏览播放图片.音视频消息时流畅不卡顿. 一.提升用户发送图片.音视频的体验 1. 多上传接入 ...
- 《即时消息技术剖析与实战》学习笔记11——IM系统如何保证服务高可用:流量控制和熔断机制
IM 系统的不可用主要有以下两个原因: 一是无法预测突发流量,即使进行了服务拆分.自动扩容,但流量增长过快时,服务已经不可用了: 二是业务中依赖的这些接口.资源不可用或变慢时,比如发消息可能需要依赖& ...
- 《即时消息技术剖析与实战》学习笔记7——IM系统的消息未读
一.什么是消息未读 消息未读包括会话未读和总未读.前者指的是当前用户和某一聊天方的未读消息数,后者指的是当前用户的所有未读消息数,也就是所有会话未读的和.比如用户A收到用户B的2条消息,还收到用户C的 ...
- 《即时消息技术剖析与实战》学习笔记8——IM系统如何保证长连接的可用性:心跳机制
假设有以下突发意外情况: 用户进入信号不好的地方,手机没有网络信号了 上网的路由器突然掉线了 这个时候,比如微信发消息,消息就会转圈圈,甚至变成红色叹号-- 上面情况都会导致"长连接&quo ...
- 《即时消息技术剖析与实战》学习笔记9——IM系统如何支持消息的多终端漫游
一.什么是多终端漫游 多终端漫游是指:用户在任意一个设备登录后,都能获取到历史的聊天记录.如:QQ 默认漫游 7 天的聊天记录,开通 VIP 会员可漫游 30 天,开通 SVIP 会员可漫游 2 年. ...
随机推荐
- 自练Eclipse搭建SSH全自动注解博客项目笔记
1.创建一个动态的java项目 2.导入搭建所需要的jar包 3.配置web.xml文件 1).头文件 2).struts2的拦截器 3).定位加载Spring容器的配置文件 4).监听 5). 6) ...
- jQuery插件之路(二)——轮播
还记得以前刚接触前端的时候,浏览各大网站,很多都少不了的有个轮播的效果,那个时候自己是一个彻彻底底的小白,想着这些图片滚动起来还真是有意思,是什么让这些图片在一个方向上连续的滚动呢.后来慢慢的接触多了 ...
- Starling 环形进度条实现
项目初期想实现这个效果来着,查了很多资料(包括式神的<神奇的滤镜>),也没找到完美的实现方法,,当时时间紧迫,就找了传统的进度条来代替实现. 最近偶然心血来潮,查了各方面资料,终于找到实现 ...
- 前端模板引擎doT.js的用法
简介 一款简单好用的前端模板引擎 用法 <script type="text/javascript" src="js/doT.min.js">< ...
- Oracle 12cR1 RAC集群安装(一)--环境准备
基本环境 操作系统版本 RedHat6.7 数据库版本 12.1.0.2 数据库名称 testdb 数据库实例 testdb1.testdb2 (一)安装服务器硬件要求 配置项目 参数要求 网卡 每台 ...
- java之异常详解
一.什么是异常? 异常就是有异于常态,和正常情况不一样,有错误出错.在java中,阻止当前方法或作用域正常运行的情况,称之为异常. 二.异常体系 Java把异常当作对象来处理,并定义一个基类java. ...
- ggplot2 |legend参数设置,图形精雕细琢
本文首发于微信公众号“生信补给站”,https://mp.weixin.qq.com/s/A5nqo6qnlt_5kF3_GIrjIA 学习了ggplot2|详解八大基本绘图要素后,就可以根据自己的需 ...
- C#/Java 动态生成电子发票
电子发票是电商时代的产物,PDF发票是最常见的电子发票之一.在这篇文章中,我将给大家分享一个免费的动态生成PDF电子发票的C#方案,并在文章末尾附上Java解决方案. 典型的发票包含客户和供应商的名称 ...
- 微服务SpringCloud之Spring Cloud Config配置中心服务化
在前面两篇Spring Cloud Config配置中心的博客中都是需要指定配置服务的地址url:spring.cloud.config.uri,客户端都是直接调用配置中心的server端来获取配置文 ...
- tensorflow中的batch_norm以及tf.control_dependencies和tf.GraphKeys.UPDATE_OPS的探究
https://blog.csdn.net/huitailangyz/article/details/85015611#