IM——分布式一致性:让你的消息支持多终端漫游

多终端漫游

是指用户在任意一个设备登录后,都能获取到历史的聊天记录

如何实现?

需要两个前置条件

1.通过设备维度的在线状态来实现 ,可以让IM服务端在收到消息后推送给接收方的多台设备,也推给发送方的其它登录设备。这样的话,就要求能够按照用户的设备维度来记录在线状态,这个其实也是支持多端登录的的一个前提

2.通过离线消息存储来实现

离线消息存储

获取离线消息的时候是接收方或者发送方的单个用户维度来获取数据的,没必要按会话来存,只需要按UID来存储即可。

此外,还有一个需要考虑的点,离线消息的存储成本是比较高的,而且我们不知道用户到底有几个设备,因此离线消息的存储一般都会有时效和条数的限制,比如保留一周时间,最多存储1000条,这样如果用户一台设备很久不登录然后某一天再上线,只能从离线消息存储中同步最近一周的历史聊天记录。

多端消息的同步机制

由于并不知道用户到底会有多少个终端来离线获取消息,我们在一个终端同步完离线消息后,并不会从离线存储中删除这些信息,而是继续保留以免后续还有该用户的其它设备上线拉取,离线消息的存储也是在不超过大小限制和时效限制的前提下,采用FIFO的淘汰机制。

所以有一个重要的问题就是,需要知道应该获取哪些离线消息,否则每次将所有离线都打包推下去,就会造成两个问题

1.浪费流浪 2.消息重复

所以需要一个机制来保证离线消息可以做到按需拉取

一种常见的方案是采用版本号来实现多终端和服务端的数据同步。

1.每个用户拥有一套自己的版本号序列空间。

2.每个版本号在该用户的序列空间都具备唯一性,一般是64位

3.当有消息或者信令需要推送给该用户时,会为每条消息或者信令生成一个版本号,并连同消息或者信令存储离线存储中,同时更新服务端维护的该用户的最新版本号。

4.客户端接收到消息或者信令后,需要更新本地的最新版本号为收到的最后一条消息或者信令的版本号。

5、当离线的用户上线时,会提交本地最新版本号到服务端,服务端比对服务端维护的该用户的最新版本号和客户单提交上来的版本号,如不一致,服务端根据客户端的版本号从离线存储获取比客户端版本号的消息和信令,并推送给当前上线的客户端。

离线消息存储超过限额了怎么办?

在用户上线获取离线消息时,会先进行客户端和服务端的版本号比较,如果版本号不一致才会从离线消息存储中,根据客户端上传的最新版本号来获取增量消息。

如果离线消息存储容量超过限制,部分增量消息被淘汰掉了,会导致根据客户端最新版本号获取增量消息失败。

解决方法:直接下推所有离线消息或者从消息的联系人列表和索引表中获取最近联系人的部分最新的消息,后续让客户端在浏览时再根据时间相关的消息ID来按页获取剩余消息,对于重复的消息让客户端根据消息ID去重。

因为消息索引表里只存储消息,并不存储操作信令,这种处理方式可能会导致部分操作信令丢失,但不会出现丢消息的情况。因此,对于资源充足而且对一致性要求高的业务场景,可以尽量提升离线消息存储的容量来提升离线存储的命中率

离线存储写入失败了会怎么样?

在处理消息发送的过程中,IM 服务端可能会出现在获取到版本号以后写入离线消息存储时
失败的情况,在这种情况下,如果版本号本身只是自增的话,会导致取离线消息时无法感知
到有消息在写离线存储时失败的情况
因为如果这一条消息写离线缓存失败,而下一条消息又成功了,这时拿着客户端版本号来取
离线消息时发现,客户端版本号在里面,还是可以正常获取离线消息的,这样就会漏推之前
写失败的那一条。
那么,怎么避免这种离线存储写失败无感知的问题呢?
一个可行的方案是可以在存储离线消息时不仅存储当前版本号,还存储上一条消息或信令的
版本号,获取消息时不仅要求客户端最新版本号在离线消息存储中存在,同时还要求离线存
储的消息通过每条消息携带的上一版本号和当前版本号能够整体串联上,否则如果离线存储
写入失败,所有消息的这两个版本号是没法串联上的。
这样,当用户上线拉取离线消息时,IM 服务端发现该用户的离线消息版本号不连续的情况
后,就可以用和离线消息存储超限一样的处理方式,从消息的联系人列表和索引表来获取最
近联系人的部分最新的消息
 

消息打包下推和压缩

对于较长时间不上线的用户,上线后需要拉取的离线消息比较多,如果一条条下推会导致整个过程很长,客户端看到的就是一条一条消息蹦出来,体验会很差。

因此,一般针对离线消息的下推会采用整体打包的方式来把多条消息合并成一个大包推下去,同时针对合并的大包还可以进一步压缩,通过降低包的大小不仅能减少网络传输时间,还能节省用户的流量消耗。

 

发布了43 篇原创文章 · 获赞 37 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_28119741/article/details/103939378