# 《分布式IM系统》大后端平台-消息服务-第06节:群聊消息的已读流程设计和实现

作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)
课程视频:https://t.zsxq.com/17Dc3UVmY (opens new window)

沉淀,成长,突破,帮助他人,成就自我。

  • 本节难度:★★☆☆☆
  • 本节重点:对群聊消息的已读流程进行设计和实现,从源码级别掌握群聊消息的已读流程,重点理解用户接收到群聊消息后,群聊消息在整个分布式IM即时通讯系统中触发已读操作的流转过程,结合自身实际项目思考,将本节学到的知识灵活应用到自身实际项目中。
  • 课程视频:https://t.zsxq.com/17Dc3UVmY (opens new window)

大家好,我是冰河~~

分布式IM即时通讯系统中大后端平台的消息微服务已经实现了单聊消息的已读流程,对于单聊消息来说,是用户直接与好友之间的聊天,对于已读消息流程,可以直接修改消息的状态。而对于群聊消息来说,是用户向某个群组发送消息,此时会有多个用户接收消息,如果每个用户接收到消息都去更新消息状态的话,显然是不太合理的。

# 一、前言

对于群聊消息的已读流程来说,与单聊消息的已读流程相比,还是有所差异的,单聊消息的已读流程中,如果好友接收到用户发送的消息,可以回调消息服务的接口来更新单聊消息的状态。但是在群聊消息的已读流程中,用户会将消息发送到群组中,此时会有多个用户接收消息,如果每个用户接收到消息都会更新消息状态,显示是不合理的。

此时,可能会有小伙伴会说,设计一张群成员与群聊消息的关系表,每发送一条消息,都向这张表中批量插入群成员与群聊消息的映射关系。但这有一个很明显的问题就是会造成高并发批量写库操作,数据库撑不住啊。

例如,一个群假设500个人,某个用户向群内发送一条消息,那么就要向群成员与群聊消息的关系表中插入500条数据,某些用户查看了消息,还要更新群成员与群聊消息的关系表中的状态,将其标记为已读。试想,最终在分布式IM即时通讯系统中不只有一个群,每个群里可能每时每刻都有用户在聊天,那这张群成员与群聊消息的关系表岂不是要爆掉?

所以,可能会有小伙伴会说,设计一张群成员与群聊消息的关系表,每发送一条消息,都向这张表中批量插入群成员与群聊消息的映射关系,这种想法是行不通的。

# 二、本节诉求

对群聊消息的已读流程进行设计和实现,从源码级别掌握群聊消息的已读流程,重点理解用户接收到群聊消息后,群聊消息在整个分布式IM即时通讯系统中触发已读操作的流转过程,并能够将本节学到的知识灵活应用到自身实际项目中。

# 三、功能描述

既然设计群成员与群聊消息的关系表这种思路行不通,那有没有更好的思路呢?其实,在之前实现群聊消息的拉取流程时,在代码层面就给大家提前透漏了相关的设计思想。我们可以在Redis中,根据用户id和群组id来分类存储用户在每个群组中已读消息的最大id,当其他用户向某个群内发送消息时,当前用户在群组内的消息未读和消息已读状态可以这样判断:消息id小于或者等于Redis中存储的当前用户在群内的已读消息最大id,那这些消息就是已读状态,否则,就是未读状态,当前用户查看消息后,再将Redis中存储的当前用户在群内的已读最大消息id更新成最新看到的消息id。

例如,用户A和用户B都在群组A中,假设Redis中存储的用户B在群组A中的已读最大消息id为100,此时用户A向群组内发送了一条消息,消息的id为101。那么对于用户B来说,群组A内的id小于或者等于100的消息都是已读状态,大于100的消息是未读状态,也就是id为101的消息是未读状态。当用户B查看群组A内的消息时,此时就需要将Redis中存储的用户B在群组A中的已读最大消息id更新成101,此时id为101的消息对用户B来说,就变成已读了。

对于群聊消息来说,我们可以在Redis中存储当前用户在群内的已读最大消息id来巧妙的解决单个用户对群聊消息未读和已读状态的问题。

# 四、流程设计

群消息的已读流程比较简单,具体如图6-1所示。


可以看到,整体流程还是比较简单的,主要涉及到用户及其所在的群组、消息微服务、消息库、分布式缓存、即时通讯SDK、消息中间件、即时通讯后端服务等

# 查看完整文章

加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码