写点什么

IM 会话阅读回执

作者:superman
  • 2021 年 12 月 18 日
  • 本文字数:2142 字

    阅读完需:约 7 分钟

1 需求

IM 单聊

消息发送人角度:显示对方已读|未读

接收人角度:本人会话的未读数

群聊

消息接收人角度:本人会话的未读数

发送人角度:群内其他人对本人发送消息的阅读情况:未读人数,已读|未读用户列表


单聊与群聊的阅读差异

单聊是一一对话,可认为对方阅读了会话最新消息就是将改会话的所有消息都读了,这样本身没问题,因为单聊下不存在一个人发很多消息对方一直没有回应,因此不存在有大量未读消息。

群聊则不同,群里的消息可能发送很多,群成员再查看群消息时,经常会有大量的未读消息,阅读时只看最近的若干条消息,并且也不继续往上看未读的历史消息。


本篇探讨单聊消息的阅读回执问题

2 单聊(会话)

2.1 产品需求

消息发送人:对方的已读/未读状态

消息接收人:多端阅读状态同步(会话的未读消息数同步)

2.2 核心问题与设计

2.2.1 核心问题

  • 及时性

消息接收人阅读状态多端同步

消息接收人阅读后同步给消息发送人

这两个事都要有及时的反馈。

  • 正确性:

        计数不可逆,没有新消息未读数不能变多

即:已读的不能变为未读

  • 离线阅读

  离线下也可以阅读,并消除本地未读计数(红点强迫症)

消除后最好可以再 app 再上线后自动将离线的阅读操作同步上报。

  • 精确性

单聊一般采用非精确方式,进入会话即视为改会话所有消息本人都已读。

  • 未读数统计

         客户端本地按消息统计

                统计本地消息库中某个时间后的消息数

问题:会有消息补偿时效问题(超期未读的消息未同步下来没有计算到未读数)。

  需要时从服务端获取

问题:存储或计算量过大

如采用实时统计:需要统计各个会话某个时间后的消息

如后端存储未读数:有消息就需要变更未读计数。

一般采用客户端统计:原因就是单聊不存在大量未读消息(按常用的使用场景来看)

  • 未读与消息同步的时效问题

1>历史消息不会全部同步下来-一般只登陆后只同步热消息(最近的-单聊可忽略,群聊不可以)

2>阅读用户角度:没有读的会话希望可以标记出来-不遗漏重要消息,即便消息很久了。

3>消息发送人角度

         对方是否阅读了本人的消息-即便很久的消息。

  • 请求量大

客户端进入单聊会话时需判断是否需要进行阅读位置更新,不需要时减少请求量。

客户端本地记录本人的阅读位置:包括本地阅读及同步的其它端的阅读位置-记录最大值。

群聊会话的阅读状态请求量会远大于消息量。

2.2.2 设计

  • 及时性

通过 IM 的长连接通道用消息或在线通知方式通知在线客户端

离线再登陆通过事件补偿推/拉 会话|消息进行同步

  • 正确性

用 IM 同一个会话中消息的顺序指标作为标记值,如 IM 本身采用消息的发送时间戳,那么阅读操作也用消息的发送时间戳,如果用递增的消息 id,那么阅读操作也使用递增的消息 id.

即便出现补偿消息补偿到了较早的消息客户端也不回退(已读功能就认为消息是严格按序到达)。

服务端或客户端更新会话阅读标记时进行比较更新,只有大于时才更新。

  • 离线阅读

客户端需要做离线记录,并上线同步。

  • 精确性

非精确,单聊多采用只记录阅读位置,不记录阅读消息。阅读回执只到会话级别。

  • 未读数计算

一般用客户端本地通过消息计算

针对历史消息可与服务端配合进行模糊性未读数补充+限量消息补偿。

超时的会话给少量最新消息,阅读位置如果小于用模糊计数表示

  • 消息同步的失效问题

产品上做阉割,超过有效期的不处理,只热消息正确即可。

效果:

阅读人角度:会话做全量同步,保证不丢会话,阅读位置小于会话消息的进行补偿拉取。

消息发送人角度:对方的阅读记录进度记录在会话上,不受消息失效限制。

 

2.3 方案

1:会话上添加阅读位置属性

      服务端会话:本人阅读位置+对方的阅读位置两个字段

阅读位置更新时,更新会话同步时间。

会话存储结构

====会话存储================================

单聊会话:

       最后一条消息 id|时间

       本人阅读位置

       对方阅读位置

 群聊:

      记录本人阅读位置用于计算本人的未读消息数

=================================================

2:进入会话,如有新消息,更新阅读位置

判断会话的阅读位置与本会话中本人为接收人的最后一条消息,如有新消息触发更新

先更新本地+再调用 server 更新(更新失败记录到待补偿任务中)

server 更新:

设置最后一条消息的时间戳:更新两个会话(本人+对方)

        触发多端同步:

            给在线其他端推送事件

            给发消息用户推送通知

3:登陆后同步

     同步消息,同步会话

会话阅读位置小于会话最后一条消息进行会话消息补偿拉取。拉取到后如果有洞未读数模糊计数。

4:客户端收到阅读更新事件

递增更新本地阅读位置(本人阅读位置|对方阅读位置)。

5:离线下本地消除

      更新本地后,记录补偿任务,上线后重新远程提交补偿任务。

6:客户端未读计算:

       消息同步后,本地消息库统计。

7:时间有效期问题(历史消息同步问题)

      消息接收人 

长久不登陆,历史消息热消息拉不下来,有未读数的单聊会话进行补偿拉取。    

即会话的历史消息即便不能全部步,但保证某个会话都有最新的几条消息,

          消息库不确定未读个数的计数用模糊(*)代替精确数。

      消息发送人

不会丢失对方的阅读信息(对方的阅读位置在会话上因此不受消息补偿的影响)。       

 

发布于: 4 小时前阅读数: 7
用户头像

superman

关注

还未添加个人签名 2018.07.20 加入

还未添加个人简介

评论

发布
暂无评论
IM会话阅读回执