即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?

 1.前言

 

 群聊已经成为主流即时通讯软件的基本功能。无论是QQ群还是微信群,群友都会在群内发送消息,因此需要对即时消息服务器进行保证:

 

 在线群组朋友可以在第一时间收到信息;

 离线群组好友可以在登录后接收消息。

 

 由于“消息风暴扩散系数”的存在(参见“在即时消息单聊和群聊中,我应该使用“推”还是“拉”进行在线状态同步”?群组消息的复杂性远远高于一对一聊天消息的复杂性。群消息的实时性、可访问性和离线消息是今天要讨论的核心话题。

 2.即时通讯开发干货系列文章

 

 本文是系列文章的第五篇,内容如下:

 

 即时消息传递保证机制的实现(一):保证在线实时消息的可靠传递

 即时消息传递保证机制的实现(二):保证离线消息的可靠传递

 如何确保即时消息的“时间”和“一致性”?》

 我应该使用“推”还是“拉”来同步即时消息单聊和群聊的在线状态?》

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?”(本条)

 安卓即时通讯智能心跳算法的设计与实现探讨(含示例代码)

 “当即时消息登录移动终端时,如何通过提取数据来节省流量?》

 易于理解:基于集群共享移动终端即时通信接入层的负载均衡方案

 浅谈移动即时通信的多点登录和消息漫游原理

 构成即时通讯开发的基础知识(一):正确理解前端HTTP单点登录接口的原理

 构成即时消息开发的基础知识(2):如何为大量图像文件设计服务器端存储架构?》

 补充即时通讯开发的基础知识(3):快速了解服务器端数据库读写分离的原理和实用建议

 构成即时消息开发的基础知识(4):正确理解短连接中的Cookie、会话和令牌

 如何实现即时通讯群聊信息的阅读回执功能?》

 即时消息群聊消息是一份拷贝(即扩散阅读)还是多份拷贝(即扩散写作)?》

 构成即时消息开发的基础知识(5):易于理解、正确理解并充分利用MQ消息队列

 一种低成本保证即时消息定时的方法探讨

 补上一课关于即时消息开发的基础知识(6):您的数据库使用NoSQL还是SQL?读读这个!》

 在即时通讯中实现“身边人”功能的原则是什么?如何有效地实现它?》

 构成即时通讯开发的基础知识(七):主流移动账户登录方法的原理和设计思路

 弥补即时通讯发展的基础知识(8):历史上最流行的,彻底了解字符乱码问题的本质

 如何实现即时通讯的扫描码板功能?有一篇文章了解主流应用的扫描代码登陆技术的原理

 “即时通讯做手机扫描码登录?让我们先来看看微信扫描码登录功能的技术原理

 构成即时通讯发展的基础知识(9):想发展即时通讯集群吗?首先了解什么是RPC!》

 

 更多群聊技术文章:

 

 即时消息群聊消息是一份拷贝(即扩散阅读)还是多份拷贝(即扩散写作)?》

 如何实现即时通讯群聊信息的阅读回执功能?》

 即时通讯群聊信息混乱的探讨

 现代即时通讯系统中聊天信息同步存储方案的探讨

 如何保证在移动即时通讯中推送大规模群组消息的效率和实时性?》

 微信后台团队:微信后台异步消息队列的优化升级实践共享

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?》

 我应该使用“推”还是“拉”来同步即时消息单聊和群聊的在线状态?》

 如何确保即时消息的“时间”和“一致性”?》

 “快速裂变:见证微信强大后台架构从0到1的演变(一)”

 一种高可用、可扩展、高并发的即时消息群聊架构的设计实践

 

 此外,如果你是即时通讯开发的初学者,强烈建议你先阅读“初学者:从零开始开发移动即时通讯”。

 3.公共群组消息流

 

 在开始讨论组消息传递过程之前,我们首先介绍两个组服务的核心数据结构:

 1234组成员表:t_group_users(group_id,user_id)组脱机消息表:t _ of fine _ msg(user _ id,group_id,sender _ id,time,msg _ id,msg _ detail)用于描述组成员

 

 

 业务场景示例:

 

 1)一个组中有五个成员:x、a、b、c和d,成员x发送消息;

 2)成员A和成员B在线,并期望实时接收消息;

 3)成员C和D处于离线状态,并期望在将来获取离线消息。

 

 系统架构介绍:

 

 1)客户端:有5个客户端用户x、a、b、c和d;

 2)服务器:

 2.1)所有模块和服务都抽象为服务器;;

 2.2)所有用户的在线状态抽象地存储在高可用性缓存中;

 2.3)所有数据信息,如组成员和组离线消息,都抽象地存储在数据库中。

 

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?_1.jpg

 

 典型的群组消息传递流程,如上图的步骤1-4所述:

 

 1、群组消息发送方x向服务器发送群组消息;

 第二步:第二步:服务器到数据库查询组中有多少用户(x,a,b,c,d);

 步骤3:3:服务器去缓存查询这些用户的在线状态;

 步骤4:对于群组中的在线用户甲和乙,群组消息服务器进行实时推送;

 以及步骤5,对于组中的离线用户c和d,组消息服务器离线存储。

 

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?_2.jpg

 

 典型的组离线消息拉取过程如上图的步骤1-3所述:

 

 1、离线消息提取器c从服务器中提取群组离线消息;

 步骤2:2:服务器从数据库中提取离线消息,并将其返回给组用户c;

 步骤3:3:服务器从数据库中删除群组用户c的群组离线消息。

 

 存在的问题:

 上述过程是最容易思考和理解的,并且存在的问题也是最明显的:对于同一组消息的内容,许多离线用户存储了许多副本。假设组中有200个离线用户,则200份离线消息是冗余的,这大大增加了数据库的存储压力。

 4.群组消息优化1:减少存储量

 

 为了减少脱机消息的冗余,添加了一个组消息表来存储所有组消息的内容。离线消息表只存储用户组离线消息的msg_id,可以大大减少数据库的冗余存储容量。想法如下。

 1234组消息表:用于存储组t _ group _ msgs(组id、发送方id、时间、消息id、消息详细信息)中的所有消息内容。组脱机消息表:优化后,将只存储精细msgs(用户id、组id、消息id)中的消息IDT

 

 

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?_3.jpg

 

 优化后,对群组在线消息进行了一些修改:

 

 第三步:每次发送在线群发信息前,先存储群发信息的内容;

 步骤6:每次存储离线消息时,只存储消息id,而不存储每个用户的消息细节。

 

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?_4.jpg

 

 当脱机消息被拉出时,响应也被修改:

 

 第一步:首先获取所有离线消息msg _ id;

 步骤3:拉消息细节;根据msg _ id

 步骤5:删除离线消息id。

 

 存在的问题(就像发送一对一的消息一样):

 1)在线消息传递中可能会出现消息丢失,如服务器重启、路由器丢包和客户端崩溃;;

 2)出于与上述相同的原因,当拉取离线消息时,也可能发生消息丢失。

 

 就像一对一消息的可靠传递一样,有必要在应用层添加确认,以确保组消息的到达。

 5.群组消息优化2:应用层确认

 

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?_5.jpg

 

 在应用层进行确认优化后,群组在线消息传递发生了一些变化:

 

 第三步:消息消息详细信息存储在群组消息表中后,无论用户是否在线,首先将消息id存储在离线消息表中;

 第六步:在线用户甲、乙收到群组消息后,需要添加应用层确认,以识别消息的到达;

 步骤7:在线用户A和B在应用层确认后删除他们的离线消息消息id。

 

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?_6.jpg

 

 对应于该组的离线消息的拉取是相同的:

 

 第一步:首先拉msg _ id;

 步骤3:拉消息细节;再次;

 步骤5:最后,应用层确认;;

 步骤6:6:服务器只有在收到应用层确认后才能删除离线消息表中的消息标识。

 

 存在的问题:

 

 1)如果消息被拉出,但没有时间进行应用层确认,是否会收到重复的消息?

 答案是肯定的,但是可以在客户端删除重复的消息id,并且不会向用户显示重复的消息id,因此不会影响用户体验

 2)对于每条离线消息,虽然只存储了消息id,但是每个用户的每条离线消息都将存储在数据库中。有什么方法可以减少脱机邮件的记录数量吗?

 

 6.群组消息优化3:离线消息表

 

 实际上,对于一个群组用户来说,在ta注销后的离线期间肯定不会收到所有的群组消息,所以没有必要为所有的离线消息存储一个离线消息id,而只需要存储最近的离线消息的时间(或消息id),并在下次登录时提取之后的所有群组消息,而不需要存储每个人都没有提取的离线消息id。

 12345组成员表:msg_id(或时间)t _ group _ users (group _ id,user _ id,last _ ack _ msg _ id(last _ ack _ msg _ time))用于描述一个组中有多少成员以及每个成员的最后一条ack组消息。不变t _ group _ msg(group _ id,sender _ id,time,msg _ id,msg _ detail)组脱机消息表:不再需要

 

 

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?_7.jpg

 

 优化离线消息表后,群发在线消息的传递过程:

 

 第三步:消息消息详细信息保存到组消息表后,不再需要操作离线消息表(消息id需要在优化前插入离线消息表);

 步骤7:在线用户A和B可以在应用层确认之后更新最后一个确认消息id(消息ID需要在优化之前从离线消息表中删除)。

 

 即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?_8.jpg

 

 群组离线消息的拉取过程类似:

 

 第一步:拉离线信息;

 步骤3:确认离线消息;

 第四步,更新最后一个确认消息id。

 

 存在的问题:

 由于“消息风暴扩散系数”的存在,假设一个组中有500个用户,“每个”组消息将成为500个应用层的确认,这将对服务器产生巨大的影响。有什么方法可以减少确认请求的数量吗?

 7.群组讯息最佳化4:批次确认

 

 由于“消息风暴扩散系数”的存在,如果每组消息都是确认消息,将会给服务器带来巨大的冲击。为了减少确认请求的数量,很容易想到批量确认。

 

 批量确认有两种方式:

 

 1)每次收到N组消息,请求量减少到原来的1/N;

 2)每隔时间间隔t执行一次组消息确认,可以达到类似效果。

 

 新问题:批量确认可能会导致用户在有时间确认组消息之前退出,这样重复的脱机消息将在下次登录时被提取。

 解决方案:msg_id是重复的,不向用户显示,从而确保良好的用户体验。

 

 还有可能出现的问题:太多的离线消息;拉得太慢了。

 解决方案:分页拉动(按需拉动)。寻呼拉取的细节在“即时消息传递保证机制的实现(第二部分):确保离线消息的可靠传递”一章中有所描述,此处不再赘述。

 8.本文摘要

 

 群组消息仍然非常有趣,例如可访问性、实时、离线消息、消息风暴传播等。,做一个总结:

 

 1)无论是群在线消息还是群离线消息,应用层的确认是可达性的保证;

 2)只存储一个组消息,而不是为每个用户存储离线组消息id,只存储一个组消息id/时间;存储最新的ack

 3)为了减少消息风暴,可以批量确认;;

 4)如果接收到重复消息,则需要复制消息标识,以便用户没有感知;

 5)离线消息太多,可以通过寻呼拉取(按需拉取)来优化。


----------------------------------------------------------------------------------

哇谷im_im即时通讯_私有云_公有云-哇谷云科技官网-JM沟通

IM下载体验 - 哇谷IM-企业云办公IM即时聊天社交系统-JM 沟通下载

IM功能与价格 - 哇谷IM-提供即时通讯IM开发-APP搭建私有化-公有云-私有化云-海外云搭建

新闻动态 - 哇谷IM-即时通讯热门动态博客聊天JM沟通APP

哇谷IM-JM沟通热门动态博客短视频娱乐生活

关于哇谷-哇谷IM-提供企业即时通讯IM开发-语音通话-APP搭建私有化-公有云-私有化云-海外云搭建

联系我们 - 哇谷IM-即时通讯IM私有化搭建提供接口与SDK及哇谷云服务

即时通讯IM融云世界

IM即时通讯钉钉技术:企业IM钉钉在后端架构上的优越之处

新的市场叫板环信、融云、腾讯云!开源版IM即使聊天工具

企业IM即时通讯聊天办公APP钉钉技术分析交流

哇谷云-怎么样正确认识海外云服务器

公有云和私有云之间有什么区别?类似融云、环信云、网易云、哇谷云?