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 里。
典型群消息投递流程,如上图步骤 1-4 所述:
- 步骤 1:群消息发送者 x 向 server 发出群消息;
- 步骤 2:server 去 db 中查询群中有多少用户 (x,A,B,C,D);
- 步骤 3:server 去 cache 中查询这些用户的在线状态;
- 步骤 4:对于群中在线的用户 A 与 B,群消息 server 进行实时推送;
- 步骤 5:对于群中离线的用户 C 与 D,群消息 server 进行离线存储。
典型的群离线消息拉取流程,如上图步骤 1-3 所述:
- 步骤 1:离线消息拉取者 C 向 server 拉取群离线消息;
- 步骤 2:server 从 db 中拉取离线消息并返回群用户 C;
- 步骤 3:server 从 db 中删除群用户 C 的群离线消息。
存在的问题:
上述流程是最容易想,也最容易理解的,存在的问题也最显而易见:对于同一份群消息的内容,多个离线用户存储了很多份。假设群中有 200 个用户离线,离线消息则冗余了 200 份,这极大的增加了数据库的存储压力。