二、已读回执流程
对于发送方发送的任何一条群消息 , 都需要知道 , 这条消息有多少人已读多少人未读 , 就需要一个基础表来记录这个关系 。
消息回执表:用来记录消息的已读回执 。
msg_acks(sender_uid, msgid, recv_uid, gid,if_ack);
各字段的含义为:发送方UID , 消息ID , 回执方UID , 群ID , 回执标记 。
增加了已读回执逻辑后 , 群消息的流程会有细微的改变 。

文章插图
步骤二 , server收到消息后 , 除了要:
- 将群消息落地
- 查询群里有哪些群成员 , 以便实施推送
- 插入每条消息的初始回执状态

文章插图
接收方修改last_ack_msgid的流程 , 会变为:
(1)发送ack请求
(2)修改last_ack_msgid , 并且 , 修改已读回执if_ack状态
(3)查询发送方在线状态
(4)向发送方实时推送已读回执(如果发送方在线)
如果发送方不在线 , ta会在下次登录的时候:
(5)从关联表里拉取每条消息的已读回执
这里的初步结论是:
- 如果发送方在线 , 会实时被推送已读回执
- 如果发送方不在线 , 会在下次在线时拉取已读回执
三、流程优化方案
再次详细的分析下 , 群消息已读回执的“消息风暴扩散系数” , 假设每个群有200个用户 , 其中20%的用户在线 , 即40各用户在线 。群用户每发送一条群消息 , 会有:
- 40个消息 , 通知给群友
- 40个ack修改last_ack_msgid , 发给服务端
- 40个已读回执 , 通知给发送方
同时:
- 需要存储40条ack记录
是否有优化方案呢?
群消息的推送 , 能否改为接收方轮询拉取?
答:不能 , 消息接收 , 实时性是核心指标 。
对于last_ack_msgid的修改 , 真的需要每个群消息都进行ack么?
答:其实不需要 , 可以批量ack , 累计收到N条群消息(例如10条) , 再向服务器发送一次last_ack_msgid的修改请求 , 同时修改这个请求之前所有请求的已读回执 , 这样就能将40个发送给服务端的ack请求量 , 降为原来的1/10 。
会带来什么副作用?
答:last_ack_msgid的作用是 , 记录接收方最近新取的一条群消息 , 如果不实时更新 , 可能导致 , 异常退出时 , 有一些群消息没来得及更新last_ack_msgid , 使得下次登陆时 , 拉取到重复的群消息 。但这不是问题 , 客户端可以根据msgid去重 , 用户体验不会受影响 。
发送方在线时 , 对于已读回执的发送 , 真的需要实时推送么?
答:其实不需要 , 发送方每发一条消息 , 会收到40个已读回执 , 采用轮询拉取(例如1分钟一次 , 一个小时也就60个请求) , 可以大大降低请求量 。
画外音:或者直接放到应用层keepalive请求里 , 做到0额外请求增加 。
会带来什么副作用?
答:已读回执更新不实时 , 最坏的情况下 , 1分钟才更新回执 。当然 , 可以根据性能与产品体验来折衷配置这个轮询时间 。
如何降低数据量?
答:回执数据不是核心数据
- 已读的消息 , 可以进行物理删除 , 而不是标记删除
- 超过N长时间的回执 , 归档或者删除掉
四、总结
对于群消息已读回执 , 一般来说:
- 如果发送方在线 , 会实时被推送已读回执
- 如果发送方不在线 , 会在下次在线时拉取已读回执
推荐阅读
- 盐酸麻黄碱
- 凤凰茶之白叶单枞,凤凰单枞茶适合人群喝
- 世上存在鬼吗 这个世上有鬼的存在吗
- 终于还是打开了这个可以学习JavaScript的教程
- 什么运动利于增高呢?
- 女孩|从完美皮肤到满脸爆痘,这个女孩的经历,让人想给她掌声
- 古树根与中国茶史千年,贵阳花溪久安乡发现五万多株千年古茶树居群,千年古茶树
- 什么是红颜知己
- 世界上最小的电脑主机 世界上容量最大的电脑
- 不可思议的神秘文化
