一、什么是消息一致性

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

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

二、消息一致性的难点

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. 在Java大环境下.NET程序员如何夺得一线生机

    先来看一组数据,从某招聘网站直接检索3-4w的岗位,会看到Java与.NET社会需求量的巨大差异,这里就不再对比高薪的岗位了,.NET的高薪岗位更是少的可怜:   笔者从业十余年,一直是在.NET圈子 ...

  2. SQL Labs刷题补坑记录(less1-less30)

    补坑加1,这几天快速刷一下sqllabs 来巩固下sql注入基础吧,也算是把很久以前没刷的过一遍,do it! 第一部分: LESS1: 直接报错,有回显的注入, http://localhost/s ...

  3. JVM总结(三)

    JVM总结(3)Class文件,类加载机制.编译过程 Java编译器先把Java代码编译为存储字节码的Class文件,再通过Class文件进行类加载. Class类文件的结构 Java编译器可以把Ja ...

  4. CSS3: perspective 3D属性

    本文引自:http://blog.csdn.net/cddcj/article/details/52956540 perspective 属性指定了观察者与z=0平面的距离,使具有三维位置变换的元素产 ...

  5. 变量Variable

    变量Variable 内存 #conding:utf-8 a = 1 #conding:utf-8 a = 1 b = a #conding:utf-8 a = 1 b = a a = 2 命名规则 ...

  6. PowerShell安装IIS

    Windows作web开发的同学,应该都会用到IIS服务器.比如在阿里云或是Azure上购买一台新的服务器,默认是没有安装IIS的(安装的镜像就带有IIS或是MySql的除外).届时需要安装IIS,安 ...

  7. Sublime Text3激活及个性化配置

    [TOC] 在我们的开发过程中,选择正确的开发工具会让我们事半功倍.作为后端开发我们熟悉的myeclipse和itellij idea这些工具我也介绍曾介绍过关于他们的安装及破解.但是我们并不能仅仅使 ...

  8. Codeforces 436D Pudding Monsters

    题意简述 开始有无限长的一段格子,有n个格子种有布丁怪兽,一开始连续的布丁怪兽算一个布丁怪兽. 每回合你可以将一个布丁怪兽向左或右移动,他会在碰到第一个布丁怪兽时停下,并与其合并. 有m个特殊格子,询 ...

  9. 前端数据双向绑定原理:Object.defineProperty()

    Object.definedProperty方法可以在一个对象上直接定义一个新的属性.或修改一个对象已经存在的属性,最终返回这个对象. Object.defineProperty(obj, prop, ...

  10. 重学计算机组成原理(十)- "烫烫烫"乱码的由来

    程序 = 算法 + 数据结构 对应到计算机的组成原理(硬件层面) 算法 --- 各种计算机指令 数据结构 --- 二进制数据 计算机用0/1组成的二进制,来表示所有信息 程序指令用到的机器码,是使用二 ...