1、前言
群聊已经成为主流IM软件的基本功能,不管是QQ群、还是微信群,一个群友在群内发了一条消息,那么对于IM服务器来说需要保证:
- 在线的群友能第一时间收到消息;
- 离线的群友能在登陆后收到消息。
由于“消息风暴扩散系数”的存在(概念详见《IM单聊和群聊中的在线状态同步应该用“推”还是“拉”span style=”color:#808080;font-size:15px;background-color:rgb(255,255,255);”>》),群消息的复杂度要远高于一对一的单聊消息。群消息的实时性、可达性、离线消息是今天将要讨论的核心话题。
2、IM开发干货系列文章
- 《IM消息送达保证机制实现(一):保证在线实时消息的可靠投递》
- 《IM消息送达保证机制实现(二):保证离线消息的可靠投递》
- 《如何保证IM实时消息的“时序性”与“一致性”
- 《IM单聊和群聊中的在线状态同步应该用“推”还是“拉”
- 《一种Android端IM智能心跳算法的设计与实现探讨(含样例代码)》
- 《移动端IM登录时拉取数据如何作到省流量
- 《通俗易懂:基于集群的移动端IM接入层负载均衡方案分享》
- 《浅谈移动端IM的多点登陆和消息漫游原理》
- 《IM开发基础知识补课(一):正确理解前置HTTP SSO单点登陆接口的原理》
- 《IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构
- 《IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议》
- 《IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token》
另外,如果您是IM开发初学者,强烈建议首先阅读《新手入门一篇就够:从零开发移动端IM》。
3、常见的群消息流程
开始讲群消息投递流程之前,先介绍两个群业务的核心数据结构:
1 2 3 4 | 群成员表:用来描述一个群里有多少成员 t_group_users(group_id, user_id) 群离线消息表:用来描述一个群成员的离线消息 t_offine_msgs(user_id, group_id, sender_id, time , msg_id, msg_detail) |
业务场景举例:
- 1)一个群中有x,A,B,C,D共5个成员,成员x发了一个消息;
- 2)成员A与B在线,期望实时收到消息;
- 3)成员C与D离线,期望未来拉取到离线消息。
系统架构简介:
- 1)客户端:x,A,B,C,D共5个客户端用户;
- 2)服务端:
2.1)所有模块与服务抽象为server;
2.2)所有用户在线状态抽象存储在高可用cache里;
2.3)所有数据信息,例如群成员、群离线消息抽象存储在db里。
- 步骤1:离线消息拉取者C向server拉取群离线消息;
- 步骤2:server从db中拉取离线消息并返回群用户C;
- 步骤3:server从db中删除群用户C的群离线消息。
存在的问题:
上述流程是最容易想,也最容易理解的,存在的问题也最显而易见:对于同一份群消息的内容,多个离线用户存储了很多份。假设群中有200个用户离线,离线消息则冗余了200份,这极大的增加了数据库的存储压力。
4、群消息优化1:减少存储量
为了减少离线消息的冗余度,增加一个群消息表,用来存储所有群消息的内容,离线消息表只存储用户的群离线消息msg_id,就能大大的降低数据库的冗余存储量,思路如下。
1 2 3 4 | 群消息表:用来存储一个群中所有的消息内容 t_group_msgs(group_id, sender_id, time ,msg_id, msg_detail) 群离线消息表:优化后只存储msg_id t_offine_msgs(user_id, group_id, msg_id) |
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!