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

 

3、常见的群消息流程

开始讲群消息投递流程之前,先介绍两个群业务的核心数据结构:

群成员表:用来描述一个群里有多少成员

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群聊消息如此复杂,如何保证不丢不重?_1.jpg

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

  • 步骤 1:群消息发送者 x 向 server 发出群消息;
  • 步骤 2:server 去 db 中查询群中有多少用户 (x,A,B,C,D);
  • 步骤 3:server 去 cache 中查询这些用户的在线状态;
  • 步骤 4:对于群中在线的用户 A 与 B,群消息 server 进行实时推送;
  • 步骤 5:对于群中离线的用户 C 与 D,群消息 server 进行离线存储。

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

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

  • 步骤 1:离线消息拉取者 C 向 server 拉取群离线消息;
  • 步骤 2:server 从 db 中拉取离线消息并返回群用户 C;
  • 步骤 3:server 从 db 中删除群用户 C 的群离线消息。

存在的问题:
上述流程是最容易想,也最容易理解的,存在的问题也最显而易见:对于同一份群消息的内容,多个离线用户存储了很多份。假设群中有 200 个用户离线,离线消息则冗余了 200 份,这极大的增加了数据库的存储压力。