一、什么是消息一致性

消息一致性指的是消息的时序一致性,即消息收发的一致性。如果不能保证时序一致性,就会造成聊天语义不连贯,引起误会。

对于点对点的聊天场景,时序一致性保证接收方的接收顺序和发送方的发出顺序一致;对于群聊场景,时序一致性保证所有接收人看到的消息展现顺序一致。

二、消息一致性的难点

1.多发送方多接收方服务端多线程并发处理情况下,无法保证时序一致性。

2.分布式环境下,多个机器的本地时钟不一致,没有“全局时钟”,不能用“本地时间”保证时序的一致性。

三、消息的一致性的实现

1. “全局序号生成器”作为“时序基准”

为什么不以客户端(发送方)的本地序号/本地时钟作为“时序基准”?

如果以发送方的本地时钟作为时序基准,发送方发送消息时,将消息本身和本地的时间戳或一个本地维护的序号发送到IM服务端,IM服务端再将这个消息和时间戳或序号发送给消息接收方,消息接收方根据这个时间戳或序号进行排序。

若发送方随时调整时钟,会导致时间戳回退;若发送方重装应用,会导致序号清零,从而回退。

而针对多发送方场景,如群聊和多点登录,存在同一时钟的某个时间点、多条消息发送给同一接收对象的可能。比如一个群聊内,用户A先发言、用户B后发言,但如果用户A的时钟比用户B的时钟慢,已发送方的本地时钟作为“时序基准”就会出问题;再比如微信在手机、电脑上同时登录,两台设备可以给某一接收方发送消息;若设备的本地时钟不一致,接收方可能会出现消息不连贯的问题。

为什么不以服务器的本地时钟作为“时序基准”?

如果以IM服务器的本地时钟作为时序基准,发送方将消息发送到IM服务端,IM服务端依据自身服务器的时钟生成一个时间戳,然后将消息和时间戳一起发送给消息接收方,消息接收方根据这个时间戳进行排序。
一旦IM服务集群化部署,就会出现多台服务器本地时钟不一致的问题。虽然多台服务器可以通过NTP时间同步服务,但依然存在一定的时间误差。

将“全局序号生成器”作为“时序基准”,可以解决每条消息没有标准“生产日期”的问题,按着实现方式可以分为两类,一是支持单调自增序号的生成,如Redis的原子自增命令incr、MySQL的自增ID,二是分布式时间相关的ID生成,如snowflake算法、时间相关的分布式序号生成服务等。
对于群聊和多点登录的场景,只需要保证一个群的消息有序即可,无需全局的跨多个群的绝对时序性。每个群聊有其独立的“ID生成器”,可以通过哈希规则路由到对应的主库实例上,降低多个群聊共用一个“ID生成器”的压力。

2.消息整流
当 IM 服务端接收到消息后,若 IM 服务器是集群化部署,可能因为服务器性能的差异,导致后收到的消息先发出去;又或者多线程处理消息的流程不能保证先到达的消息先发送出去,从而使接收方收到的消息顺序有误,因此需要消息整流。消息整流又分为服务端包内整流和客户端(接收方)整流。

  • 服务端包内整流

    比如实现离线推送,当用户上线,网关机会通知业务层用户已上线,业务层就会把该用户的多条离线消息 pub 给这个网关机的 Topic,网关机再把收到的多条消息通过长连接推送给用户。

    图片来源于《即时消息技术剖析与实战》第 05 讲

    1)生产者为每个消息包生成一个packageID,为包内的每条消息加个有序自增的seqID;

    2)消费者根据每条消息的packageID 和 seqID 进行整流和排序;

    3)执行模块只有在一定超时时间内完整有序地收到所有消息才执行最终操作,否则根据业务需要触发重试或直接放弃操作。

  • 消息接收端整流

    1)发送方发送消息时,连同消息和序号一起发送给接收方;

    2)接收方接收到消息后,先去查找上一条消息的序号,然后比对收到的序号和上一条消息的序号;

    3)如果收到的消息序号大于上一条消息序号,直接追加;反之则去查找小于该序号的最大消息序号,并追加到其后。

四、参考

消息时序一致性还可以参考58沈剑大佬的文章:消息“时序”与“一致性”为何这么难?,又会有不一样的收货。

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

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

    IM 系统中,保证消息的可靠投递主要体现在两方面,一是消息的不丢失,二是消息的不重复. 一.消息不丢失 消息丢失的原因 首先看一下发送消息的流程,如下图所示: 消息.可以采取"时间戳比对&q ...

  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. Vue系列:Vue Router 路由梳理

    Vue Router 是 Vue.js 官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌.包含的功能有: 嵌套的路由/视图表 模块化的.基于组件的路由配置 路由参数. ...

  2. TP5使用API时不可预知的内部异常

    最常见的错误形式例如 controller不存在或者 action不存在之类的 我们第一时间想到的 就是 使用 try{}catch(){} 来捕获 例如: /** * show方法在common里定 ...

  3. 开发规范 小白进阶 python代码规范化

    开发规范 软件开发,规范项目的目录结构,代码规范,遵循 PeP8规范等等,让你更加清晰的,合理开发 一功能分类(文件名) settings.py配置文件 配置文件放一些静态参数, 划归固定的路径,文件 ...

  4. 基于sparksql collect_list的udf定义踩坑

    多条collect_list,然后将collect_list的结果concat起来,最初使用的是concat_ws(),但是发现超过4个collect_list就会报错, select concat_ ...

  5. nessus安装

    1.安装注册 (1)从https://www.tenable.com/products/nessus/select-your-operating-system上下载对应操作系统版本的nessus,结果 ...

  6. HBase 系列(五)——HBase 常用 Shell 命令

    一.基本命令 打开 Hbase Shell: # hbase shell 1.1 获取帮助 # 获取帮助 help # 获取命令的详细信息 help 'status' 1.2 查看服务器状态 stat ...

  7. Java中synchronized关键字你知道多少

    1.什么是synchronized 我们将其理解为同步锁,可以实现共享资源的同步访问,解决线程并发的安全问题.synchronize翻译成中文:同步,使同步.synchronized:已同步. 1.1 ...

  8. 神经网络 OCR 参考

    1. https://blog.csdn.net/u010159842/article/details/87271554 2. https://blog.csdn.net/weixin_4286104 ...

  9. [原创] Nginx1.13版本reload过程对TCP包影响的测试

    Nginx1.13版本reload过程中各项连接情况和状态的测试.测试Nginx1.13 Reload过程中,对客户端和服务器的TCP层面的包影响.     1)对客户端开启长连接,服务端开启/不开启 ...

  10. 使用Eclipse开发动态Javaweb项目

    使用Eclipse开发动态Javaweb项目 一.Eclipse的使用 1. 把开发选项切换到 JavaEE 2. 可以在 Window -> Show View 中找到 Package Exp ...