IM群聊消息如此复杂,如何保证不丢不重?

1、前言


群聊已经成为主流IM软件的基本功能,不管是QQ群、还是微信群,一个群友在群内发了一条消息,那么对于IM服务器来说需要保证:

  • 在线的群友能第一时间收到消息;
  • 离线的群友能在登陆后收到消息。


由于“消息风暴扩散系数”的存在(概念详见《IM单聊和群聊中的在线状态同步应该用“推”还是“拉”span style=”color:#808080;font-size:15px;background-color:rgb(255,255,255);”>》),群消息的复杂度要远高于一对一的单聊消息。群消息的实时性、可达性、离线消息是今天将要讨论的核心话题。

2、IM开发干货系列文章


本文是系列文章中的第5篇,总目录如下:

  • 《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里。


IM群聊消息如此复杂,如何保证不丢不重2.jpg 

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

  • 步骤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)


IM群聊消息如此复杂,如何保证不丢不重3.jpg 

来源:varyall

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2018年4月3日
下一篇 2018年4月3日

相关推荐