即时消息群聊新闻如此复杂,如何确保它不丢失或沉重?
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-提供企业即时通讯IM开发-语音通话-APP搭建私有化-公有云-私有化云-海外云搭建
联系我们 - 哇谷IM-即时通讯IM私有化搭建提供接口与SDK及哇谷云服务
公有云和私有云之间有什么区别?类似融云、环信云、网易云、哇谷云?