即时通信IM聊天消息顺序之ID生成策略

开发一款即时通信的聊天软件,或者说近实时的聊天软件,最基本的要求,就是要保证消息的顺序,这个顺序指的是在发送者的角度来讲,发送者发送消息的时候,顺序是一个样子,在退出聊天页,或者重新登录之后,再次进入到聊天界面,看到的顺序任然是退出之前的样子,不能让消息的顺序出现跳动,

如果这个基本要求不能保证,就会导致刷新聊天界面之后,或者说退出再次进入聊天界面之后,消息的顺序和发送消息时的顺序不一样,就像下面这样:
在这里插入图片描述
从消息的接收者的角度来看,允许接收者视角和发送者视角看到的消息顺序不一致。比如下面的截图:
在这里插入图片描述

消息接收者和发送者的手机屏幕上,消息的顺序就是不一致,接收者并不知道消息发送者真实的发送顺序是怎么样的,这并不影响双方的对话。导致这种情况可能是网络延迟的问题,比如发送者第一条消息发送的是图片,第二条消息发送的是纯文字,由于网络延迟的原因,接收者收到消息的时候,先收到文字,后收到图片,这样就导致接收者和发送者看到的顺序不一致,这种情况是允许存在的。

但是上面说的第一种情况,就不能允许了,即同一个视角下,刷新界面前后,顺序改变,跳消息,怎么来设计,才能避免跳消息这种情况呢?最主要还是在消息ID的设计上。

聊天界面消息的排序,涉及到两种消息ID,一种是全局消息ID,一种是是本地消息ID,本地指的就是聊天界面,不管是消息的发送者还是接收者。

服务端需要提供一个ID生成接口,专门用于生成全局的消息ID,全局的消息ID需要保证严格的单调递增,才不会影响消息的排序,ID生成规则可以是:时间戳(秒)+自增ID,也可以是其他的生成策略,原则就是单调递增,切不能重复。

本地消息id(localId)生成策略:

  1. 如果本地没有上一条消息,第一条本地消息ID localId=从服务器获取一个全局msgId*100。
  2. 接收到的消息localId=msgID*100
  3. 上条消息是非本地的,当前消息的localId =上个消息的msgId*100+1
  4. 上条消息是本地的,当前消息的localId =上个localId+1

消息发送到服务器之后,localId会随着消息一起存储在数据库中,本地使用localId排序。

为什么消息ID要乘以100(也可以加100)?

为了防止这种情况的发生,如果客户端发送了100条消息,但是只有10条消息发送出去,如果此时接收到一条来自服务端的消息,该消息的localId=msgId*100就可以将该条消息排序在客户端的100条消息之后。这样,当清空本地消息,从服务端重新拉取消息时,展现时,不至于出现,这条服务端的消息插在100条客户端消息的中间。

猜你喜欢

转载自blog.csdn.net/lihuayong/article/details/108218729