IM 内容分享(十二): 未读数逻辑实现

文章详细探讨了IM系统中离线存储模型和在线存储模型的实现原理,指出离线存储适用于高在线率的PC时代,而在线存储则更适合移动互联网,通过减少数据传输和提高用户体验来优化消息未读数的统计和处理。
摘要由CSDN通过智能技术生成

目录

一、离线存储模型

二、在线存储模型

总结文中关键


在 IM 系统中,“未读数” 是一个非常核心的概念。

首先,从产品体验上,用户登录之后,往往是由消息 “未读数” 引导用户后续的操作;其次,“未读数” 实现逻辑直接影响了上层业务的核心设计;轻量级的未读数模型,会大大降低服务端负载,提升性能,减少损耗。

IM 的未读数模型包括 “离线存储模型” 和 “在线存储模型”,我们今天结合场景深入分析。

一、离线存储模型

所谓未读数的离线存储模型,是指消息未读数的统计和计算需要借助于离线消息库,见下图场景。

  • 当用户 uid=101 发一条消息给离线用户 uid=102 时,处理的逻辑是向 “离线库” 写入一条记录,向 “云消息库” 写入两条记录;

  • 当用户 uid=101 发一条消息给在线用户 uid=102 时,处理的逻辑是只向 “云消息库” 写入两条记录;

  • 当用户 uid=102 登录后,会首先从 “离线库” 中拉取所有的离线消息记录到客户端本地,这些离线消息记录的条数是客户端未读数的一部分,还有一部分是已经在客户端本地但未被用户阅读的消息(这是客户端逻辑,不在本文讨论范围)。

可以这样简单来理解未读数的离线存储模型:

  1. 当用户处于在线状态时,客户端收到消息后,未读数的统计完全由客户端来计算;

  2. 当用户处于离线状态时,由离线库存储所有的离线消息,用户登录后,离线消息全部拉取到客户端,由客户端统计未读数。

未读数的离线存储模型,很容易理解,也方便落地实现,但是绝非轻量。

当用户有大量的离线消息时,尤其是用户有非常多的群消息时,哪怕用户对这些消息并不关注,在登录的时候也都需要将这些离线消息拉取到客户端本地;这让登录逻辑会很重,也消耗了客户端很多的网络带宽。

所以,离线存储模型适合于用户在线率比较高的 PC 时代的 IM 应用,并不适合移动互联网场景。

二、在线存储模型

在未读数的离线存储模型中,“离线库” 中的数据其实是 “云消息库” 中部分数据的冗余,所以完全可以舍弃 “离线库”,并通过在 “云消息库” 中进行标注来识别出 “离线” 或 “未读”,这就是未读数的在线存储模型。见下图场景。

未读数的在线存储模型,不关注消息是否是离线的,只关注发送到服务端的消息,有多少条是还未到达接收方客户端的,这里的 ”多少条“ 即消息未读数,由联系人表的一个扩展字段 unread 来负责存储。

  • 用户 uid=101 发一条消息给用户 uid=102,不管用户 uid=102 是在线状态还是离线状态,服务端都需要向云消息库写两条记录,向联系人库更新两条记录;联系人库中,对于 uid=102 的记录,其 unread 字段需要执行加1的操作(unread++);

  • 用户 uid=102 登录后,需要首先从联系人库中,读取其所有未读的消息数量,即 unread;可以对比离线存储模型,在线存储模型中只需要从服务端获取一个数值,而离线存储模型则需要获取所有的离线消息;

  • 用户 uid=102 在未读数的引导下,会进入与好友的聊天窗口,通过不断滑动屏幕,触发拉取历史消息的操作,即服务端会从云消息库中分页读取历史消息;这一步是在用户的操作之下进行的,用户对哪个联系人感兴趣,就拉取哪个联系人的消息,按时间顺序由近及远,倒序拉取;

  • 消息拉取到客户端本地后,需要对服务端联系人库中的 unread 字段进行重置;需要注意,不是将 unread 重置为 零;用户 uid=102 在与好友的聊天窗口中,将最新的一条消息记录的标识,即 last_msg_id ,作为参数传递到服务端,服务端根据 last_msg_id 查询云消息库,获取比 last_msg_id 更大的消息记录数,然后将此数来重置未读数字段 unread(大家思考一下,为什么需要这样操作);重置未读数的时机有两个:一是用户进入与好友的聊天窗口时,二是用户离开聊天窗口时。

这就是整个未读数的在线存储模型的基本逻辑,与离线存储模型相比,轻量很多;首先是用户登录时,只需要从服务端获取一个未读数值;然后根据用户操作,按需要拉取历史消息,这大大节省了用户的网络带宽,用户操作更轻便,体验更流畅。所以,未读数的在线存储模型更适合移动互联网场景下的 IM 应用。

为了方便大家,对未读数在线存储模型的核心逻辑理解更深刻,我们从数据表的视角再深入分析一下,见下图。

  • 图中左侧是用户 uid=102 的云消息记录,共有 5 条,分别是 uid=101 和 uid=103 发送的;

  • 图中右侧是用户 uid=102 的联系人记录,其联系人是 uid=103,该联系人曾发送 3 条消息给 uid=102,所以未读数是 unread=3;

  • 任何一个用户发送消息给 uid=102 时,都需要执行两步操作:对云消息表追加记录,对联系人表更新未读数(unread++);

  • 对于用户 uid=102,登录时触发 “拉未读数” 的操作,即从联系人表读取 unread,比如:拉取联系人 uid=103 的消息未读数是 3;

  • 在未读数的引导下,用户 uid=102 进入与 uid=103 的聊天窗口中,通过滑动屏幕触发 “拉云消息” 的操作,即从云消息表中倒序分页拉取消息记录;

  • 用户 uid=102 离开聊天窗口时触发 “重置未读” 的操作,假设 uid=103 发送的三条消息全部被 uid=102 拉取到了本地,则将最新的消息记录标识 last_msg_id=5 作为参数传递到服务端,服务端对云消息表执行 【select count(*) from 云消息表 where to_uid=102 and from_uid=103 and msg_id > 5】,然后将获取的结果 0 对联系人表执行 【update 联系人表 set unread=0 where to_uid=102 and from_uid=103】。

在未读数在线存储模型中,服务端需要提供三个最核心的接口:拉未读数、拉云消息、重置未读。

总结文中关键

  1. IM 的未读数会引导用户操作,影响业务流程设计,其实现包括 “离线存储模型” 和 “在线存储模型”;

  2. 离线存储模型,其消息统计借助于离线消息库,用户登录后将所有离线消息拉取到客户端本地进行计算;离线存储模型适合用户在线率较高的 PC 时代的 IM 应用;

  3. 在线存储模型,其消息统计借助于联系人表的 unread 字段,用户登录后通过读取联系人表获取未读数,通过读取云消息表获取历史记录;在线存储模型适合移动互联网下的 IM 应用。

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值