理解IM消息“可靠性”和“一致性”问题,以及解决方案探讨
试想如果一个IM连发出的消息都不知道对方到底能不能收到、发出的聊天内容对方看到的到底是不是“胡言乱语”(严重乱序问题),这样的APP用户肯定不会让他在手机上过夜(肯定第一时间卸载了),因为最基本的聊天逻辑都无法实现,它已经失去了IM软件本身的意义。

不过,另一个方面来讲,IM系统是不标准的(虽然曾经XMPP这种协议试图解决这个问题,但事实证明那根本不现实),各家几乎都是自已的私有协议、不同的实现逻辑,这也决定了即使同一个技术问题,对于IM来说很难有固定的实现套路和标准的解决方案。
所以,对于本文来说,文中作者虽然提供了有关IM消息“可靠性”与“一致性”问题的解决方案,但方案到底合不合理、适不适合你,这就是仁者见仁、智者见智的事了。用人话说就是:本文内容仅供参考,具体的解决方案请务结合自已的系统构架和实现情况,多阅读几篇即时通讯网上有关这个技术话题的文章,取其精华,找到适合自已的技术方案和思路才是最明智的。
丛所周之,即时通讯聊天(IM)系统必需要解决消息可靠性及消息一致性问题(PS:如果具体IM系统是什么你都还没弄明白
这两个问题,通俗来说就是:
1)消息可靠性:简单来说就是不丢消息,会话一方发送消息,消息成功到达对方并正确显示;2)消息一致性:包括发送一方消息一致及会话双方消息一致,要求消息不重复,不乱序。
本文会从典型的IM消息发送逻辑开始,简单易懂地阐明消息可靠性、一致性问题的原理及可参考的技术解决方法,或许技术方案并不完美,但希望能为你的IM技术问题解决带来启发。
IM的消息发送一般的实现过程可以分为两个阶段:
1)发送方发送消息、服务端接收、返回消息 ACK 给发送方;2)服务端将消息推送到接收方。
判断消息发送是否成功主要依据第一阶段——即服务器是否接受到消息。
对于消息发送者来说,消息状态可以分为三类:
1)正在发送;2)发送成功;3)发送失败。
具体来说,这三类状态的具体意义是:
1)正在发送:发送方触发发送事件开始,到收到服务端返回消息对应 ACK 之前;2)发送成功:发送方收到消息对应 ACK 回复;3)发送失败:超过一定重发次数,未收到消息对应 ACK 回复。即时通讯聊天软件app开发可以加小蓝豆的v:weikeyun24咨询

4.1 重发机制
保证消息发送第一阶段(见本文“3、典型IM消息发送过程”一节)消息成功发送的方法是设立重发机制:
1)依据一定时长内是否收到消息对应 ACK,判断消息是否要重发;2)如果超过预设时长,就重新发送;3)当重发次数超过预设次数,就不再重发,判定该消息发送失败,修改消息发送状态。
PS:具体的完整方案级代码实现,可以参考MobileIMSDK 中有关QoS机制的代码实现。
4.2 会话记录检查
消息发送第二阶段(见本文“3、典型IM消息发送过程”一节)服务端推送消息到接收方,如果连接断开,会丢失消息。
所以要保证消息完整,就需要在建立连接后,根据上一条消息(已经 ACK)时间戳,获取会话记录,一次返回一段时间内所有消息(PS:中大型应用中,消息的拉取也不是个简单事情,
4.3 需要考虑的两个问题
消息重发、会话记录检查需要考虑两个问题:
1)消息是否会重复发送;2)消息顺序是否会被打乱。
举两个例子。
关于消息重发问题:
1)如果丢消息的点在消息达到服务端之前,服务端并没有收到消息,发送方重新发送丢失消息,服务端接收成功,不会产生两条相同消息;2)而如果服务端接收到消息,返回 ACK 丢失,这时再发送一次相同消息,就可能造成消息重复。
关于消息顺序问题:
1)如果发送方连发三条消息,第一、第三条成功被服务端接收,第二条丢了,那第三条消息是否会被记录?2)如果这时第二条消息达到服务端,其顺序是在第三条时间之前还是之后(服务端一般都会给记录打一个时间戳)?
5.2 使用向量时钟进行消息排序
对于消息排序问题:因为在聊天中,消息的顺序对于发送方的表述有重要的影响,消息不完整或顺序颠倒都可能造成语意不连贯,甚至曲解。所以需要保证发送方发送消息顺序,而会话双方消息排序需要考虑实际情况。
在一般的认知里:状态是正在发送的消息,应该还没有被对方看到,只有发送成功的消息,才会被对方看到。但在实现中,消息发送成功是以服务器接收消息并返回 ACK 成功为判断依据,而不是被对方接收到。
那么就会出现这样一个问题:如果一条消息状态是正在发送,此时收到一条消息,那么收到的消息是在正在发送的消息之前还是之后?
这是一个上下文关系,关键问题是:发送方是以哪条所见消息为依据发送消息的。
这里提供一种思路:借鉴分布式系统中的向量时钟算法(见《分布式系统中的向量时钟算法》)。
先简单描述向量时钟算法:
向量时钟算法用于在分布式系统中生成事件偏序关系,并纠正因果关系。一个系统包含 N 个节点,每个节点产生的消息体中包含该节点的逻辑时钟,整体系统的向量时钟由 N 维逻辑时钟组成,并在每个节点产生的消息体中传递。
简单来说,向量时钟算法的实现原理如下:
1)初始状态,向量值为 0;2)每次节点处理完节点事件,该节点时钟+1;3)每次节点发送消息,将包含自身时钟的系统向量时钟一起发送;4)每次节点收到消息,更新向量时钟,该节点时钟+1,其他节点对比每个节点本地保留的向量时钟值和消息体中向量时钟值,取最大值;5)节点同时收到多条消息,判断接收消息的向量时钟之间是否存在偏序关系。
相关文章:
理解IM消息“可靠性”和“一致性”问题,以及解决方案探讨
试想如果一个IM连发出的消息都不知道对方到底能不能收到、发出的聊天内容对方看到的到底是不是“胡言乱语”(严重乱序问题),这样的APP用户肯定不会让他在手机上过夜(肯定第一时间卸载了),因为最基本的聊天逻…...
2021-08-29
服务器 主:172.17.0.2 master 备:172.17.0.3 slave1 lvs虚拟IP:172.17.0.100 #nginx下载地址 http://nginx.org/download/ 本地文件路径 1.dockerfile构建nginx FROM centos:7 ADD nginx-1.6.0.tar.gz /usr/local COPY nginx_install.sh /usr/local RUN sh …...
第八题、哈夫曼编码大全
题目: 哈夫曼编码大全 描述: 关于哈夫曼树的建立,编码,解码。 输入 第一行输入数字N,代表总共有多少个字符以及权值 第二第三行分别是一行字符串,以及每个字符对应的权值 接下来输入一个数M,表…...
linux集群技术(二)--keepalived(高可用集群)(二)
案例1--keepalived案例2--keepalived Lvs集群1.案例1--keepalived 1.1 环境 初识keepalived,实现web服务器的高可用集群。 Server1: 192.168.26.144 Server2: 192.168.26.169 VIP: 192.168.26.190 1.2 server1 创建etc下的…...
C# 控制台程序的开发和打包为一个exe文件
目录前言一、我的第一个C#控制台程序二、发布为一个exe文件前言 本文通过C#编写一个简单的示例计算器,来演示C#的使用和使用 Visual Studio 打包为一个 exe 文件。 一、我的第一个C#控制台程序 所谓控制台程序,就是没有界面,运行程序后只有…...
Redis实战案例
文章目录1、SpringBoot整合Redis1.1、新建项目1.2、接口编写1.3、集成Redis1.3、测试1.4、序列化问题2、Redis实现分布式缓存2.1、背景介绍2.2、代码编写2.3、缓存改造2.4、小结3、RedisAOP自定义注解,优雅实现分布式缓存3.1、自定义注解3.2、AOP切面类3.3、测试3.4…...
slice和splice区别
slice和splice区别 splice和slice是数组中的两个重要的方法。 slicesplice不会改变原数组改变原数组返回原数组中的部分元素返回原数组中被删除的元素组成的新数组用来选择数组中的元素用于在数组中插入或者删除元素 1.splice的语法 array.splice(index,howmany,item1,…,ite…...
动态规划从入门到精通-蓝桥杯
一、了解动态规划1.简单来说动态规划是一种状态转移与递推2.例题引入——最少硬币问题有多个不同面值的硬币(任意面值); 数量不限; 输入金额S,输出最少硬币组合。 (回顾用贪心求解硬币问题。)贪心法硬币面值1、2、5。支…...
Docker部署Prometheus
文章目录Prometheus相关介绍Docker部署Prometheus说明安装Prometheus搜索镜像拉取镜像配置启动容器进入容器遇到的问题Are you trying to mount a directory onto a file (or vice-versa)?其他可能的错误Prometheus相关介绍 官方介绍,非常的清楚: http…...
JavaScript的执行顺序
前言 在说 JavaScript 的执行顺序之前,我们先回答一下以下几组程序的输出结果 第 1 组 const output (v) > {console.log(v); };setTimeout(() > {console.log(1); }, 0); output(2); console.log(3);// 2 3 1第 2 组 new Promise((resolve) > {conso…...
C++11智能指针std::shared_ptr介绍及使用
介绍 shared_ptr是一种智能指针(smart pointer),作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。这便是所谓的引用计数(reference counting),比如我们把只能指针赋值给另外一个对象,那么对象多了一个智能指针指向它,所以这个时候引用计数…...
华为OD机试 - 数字的排列(Python) | 机试题+算法思路+考点+代码解析 【2023】
数字的排列 题目 小华是个很有对数字很敏感的小朋友, 他觉得数字的不同排列方式有特殊的美感。 某天,小华突发奇想,如果数字多行排列, 第一行1个数, 第二行2个, 第三行3个, 即第n行n个数字,并且奇数行正序排列, 偶数行逆序排列,数字依次累加。 这样排列的数字一定很…...
Android 事件分发机制(4)-常见面试题
目录 1.你了解过Android的事件分发机制吗?请大致介绍一下 2、如果父view中不拦截down事件,拦截move,up事件,在子view中设置了requestDisallowInterceptTouchEvent(true);(请求父view不拦截事件)这个标志后,…...
计算机四级 [操作系统] | 选择题 2 重点标注版
1.某一个单道批处理系统几乎同时依次到达4个作业,这4个作业的预计运行时间分别为8、4、4和4分钟,按照短作业优先的调度算法运行,请问该批作业的平均周转时间为多少 B A. 14分钟 B. 11分钟 C. 20分钟 D. 10分钟 2.下列与进程具有一一对应的关…...
想玩好ChatGPT?不妨看看这篇文章
相信点进来的铁汁,此时已经对 ChatGPT 有所了解,并想上手体验一番 首先大伙儿要注意,不要被骗了。 现在很多商家提供的 ChatGPT 服务,不仅价格奇高,而且据我所知,有些压根不是 ChatGPT 。 想玩最好去官网注册,具体方法大伙自个儿查一查嗷。 怎么用好 ChatGPT 虽然 …...
day31 IO流
文章目录回顾collectionArrayTestListHashSetTsetHashMapTestPropertiesTreeSetTestIO流FileInputStreamTest01 文件流初步FileInputStreamTest02 循环读FileStreamTest03FileInputStreamTes04 需要掌握FiLeInputStreamTest5FileOutputStreamTest01Copy1 文件拷贝FileReaderTes…...
Linux 防火墙配置(iptables和firewalld)
目录 防火墙基本概念 Iptables讲解 Iptables表 Iptables规则链 Iptables控制类型 Iptables命令配置 firewalld讲解 Firewalld区域概念 Firewalld两种配置方法 firewall-cmd命令行基础配置 firewall-config图形化配置 防火墙基本概念 防火墙就是根据系统管理员设定的…...
深度学习基础(一)
记得17年第一次阅读深度学习相关文献及代码觉得不是很顺畅,做客户端开发时间久了,思维惯性往往觉得比较迷茫。 而且文章中涉及的数学公式及各种符号又觉得很迷惑,虽然文章读下来了,代码也调试过了,意识里并没有轻松的…...
Maven 常用命令
mvn archetype: create :创建Maven 项目mvn compile :编译源代码。mvn deploy:发布项目。mvn test-compile :编译测试源代码mvn test:运行应用程序中的单元测试mvn site:生成项目相关信息的网站mvn clean:清除项目目录中的生成结果mvn package:根据项目生成的iar/war等mvn inst…...
2023年100道最新Android面试题,常见面试题及答案汇总
除了需要掌握牢固的专业技术之外,还需要刷更多的面试去在众多的面试者中杀出重围。小编特意整理了100道Android面试题,送给大家,希望大家都能顺利通过面试,拿下高薪。赶紧拿去吧~~文末有答案Q1.组件化和arouter原理Q2.自定义view&…...
为什么选择ODB++格式?Cadence与HyperLynx数据交换的最佳实践
为什么选择ODB格式?Cadence与HyperLynx数据交换的最佳实践 在高速PCB设计领域,数据格式的选择直接影响着设计到制造的整个流程效率。当工程师需要在Cadence Allegro和HyperLynx之间传递设计数据时,ODB正逐渐成为行业首选。这种智能数据格式不…...
OpenCode应用案例:搭建企业内部代码审查助手,提升开发效率
OpenCode应用案例:搭建企业内部代码审查助手,提升开发效率 1. 项目背景与痛点分析 在软件开发团队中,代码审查是保证代码质量的关键环节。然而传统人工审查方式面临诸多挑战: 时间成本高:资深工程师需要花费大量时间…...
别再只加Mask了!手把手教你用FlashAttention实现真正的Sliding Window Attention(附代码)
突破传统误区:用FlashAttention实现高效滑动窗口注意力的实战指南 在Transformer模型优化领域,许多开发者对滑动窗口注意力(Sliding Window Attention, SWA)存在一个普遍误解——认为只需在注意力矩阵上添加滑动窗口掩码就能实现线性复杂度。这种错误认…...
RouterOS网桥VLAN实战:从零构建安全隔离的二层虚拟网络
1. VLAN基础与RouterOS网桥概述 刚接触网络管理的朋友可能经常听到"VLAN"这个词,但总觉得它神秘莫测。其实VLAN就像给一栋办公楼划分不同部门:财务部、研发部、市场部各自有独立的办公区域,既保证了隐私安全,又避免了相…...
Benchmark.js 配置选项终极指南:如何优化你的 JavaScript 性能测试环境
Benchmark.js 配置选项终极指南:如何优化你的 JavaScript 性能测试环境 【免费下载链接】benchmark.js A benchmarking library. As used on jsPerf.com. 项目地址: https://gitcode.com/gh_mirrors/be/benchmark.js Benchmark.js 是一款专业的 JavaScript 性…...
7个实用技巧:从零开始开发jquery-qrcode自定义二维码生成器
7个实用技巧:从零开始开发jquery-qrcode自定义二维码生成器 【免费下载链接】jquery-qrcode qrcode generation standalone (doesnt depend on external services) 项目地址: https://gitcode.com/gh_mirrors/jq/jquery-qrcode jquery-qrcode是一款轻量级的纯…...
FlexRay帧格式拆解:从Header到Trailer,手把手教你读懂汽车总线的‘数据包’
FlexRay帧格式实战解析:像拆解网络包一样掌握汽车总线通信 在汽车电子系统开发中,理解总线协议就像网络工程师需要精通TCP/IP一样重要。FlexRay作为高性能车载网络的核心协议,其帧格式设计既体现了汽车电子对确定性的严苛要求,又融…...
Hunyuan-MT-7B效果实测:Pixel Language Portal对中文网络用语、方言、谐音梗的跨维转码能力分析
Hunyuan-MT-7B效果实测:Pixel Language Portal对中文网络用语、方言、谐音梗的跨维转码能力分析 1. 引言:当翻译遇上像素冒险 在数字时代的语言交流中,传统翻译工具往往显得生硬而缺乏温度。Pixel Language Portal(像素语言跨维…...
深度探索:开源工具OpenCore Legacy Patcher技术揭秘与完整指南
深度探索:开源工具OpenCore Legacy Patcher技术揭秘与完整指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 随着苹果系统持续演进,…...
Java AI推理服务上线即崩?JVM GC日志暴露真相:Metaspace暴涨470%、Direct Memory泄漏12.6GB——5行代码精准修复方案(含Arthas实时监控脚本)
第一章:Java AI推理服务集成概述在现代企业级AI应用架构中,Java凭借其稳定性、丰富的生态和成熟的微服务支持能力,正成为部署AI推理服务的重要后端语言。与Python主导的模型训练场景不同,Java更常用于高并发、低延迟、强事务保障的…...
