IM系统如何保证消息顺序性?

保证消息发送顺序难点来自于

  • 分布式系统下,时钟不一致,没有全局时钟

    多个客户端、服务器之间的时钟可能大相径庭

  • 多客户端,导致接收顺序不一定

    在绝对时序上,若client1先发出msg1,而后client2发出msg2,那么是无法保证msg1一定先于msg2到达

  • 服务集群,难以协调消息顺序

    在绝对时序上,若client发出msg1,而后client发出msg2,那么由于服务器集群存在,是无法保证msg1一定先被接收处理

  • 网络传输与多线程,不保证传输和处理顺序

    在绝对时序上,若client发出msg1,而后client发出msg2,可能网络原因导致msg2反而先到,或者由于多线程处理的存在,导致msg2先被处理

单对单聊天,保证发送与接收顺序一致

发送方标记消息顺序

发送方可以根据发送顺序生成标识来区分顺序,该标识可以是

  • 生成的单调递增序列号

    可以为每个单对单会话生成递增id,唯一的问题可能就是会溢出,但一般也不会溢出,即使溢出处理之后还是能保证顺序性

  • 本地时间戳

保证接收展示顺序

在集群中最关键的是保证尽量按照顺序发送消息给接收方,以及配合接收方保证展示顺序

而接收方要根据传输过来数据去保证展示顺序

  • 保证发送方与集群机器匹配,集群机器保证前一条展示正确后发送后一条

    消息只能一条发完,再发下一条,性能损耗过大

  • 基于每个会话单调递增序列号的情况下,集群不做额外处理直接发给接收方,接收方严格按照顺序展示消息

    比如接收方收到了1、3,那么消息1可以展示,而消息3在消息2没有接收到之前都不可以展示

  • 接收方纠错。若新接收消息顺序早于展示的消息,那么就刷新展示顺序

    给用户展示的消息不具有一致性,这可能会引发误解,但若用户能理解,那么也不失为一个好的解决方法

  • 接收方每条消息等待一定时间后展示。也就是说如果一条消息在一定时间内没有其他消息顺序在其前,那么就直接展示

    时效性较差,并且也无法充分保证顺序

群聊:以服务器接收时间为准

  • 发送者对群聊会话hash到特定服务器x,由x进行统一处理

    由x推送到接收者更好还是发送者拉取?

    个人认为接收者客户端情况可能已经下线了,会产生很多不必要的推送以及维护很多不必要的连接

    如果x出现故障呢?

    那么为了防止消息丢失,只有在所有接收者收到消息后才确定该条消息消费完成,否则在等待一定时间后发现仍未完成,则会重试其他服务器或者直接提示发送失败,并且在接收端做好幂等处理

    但这样做,在存在客户端长期下线的情况下等待周期过长。如果发送者客户端不等待,又容易丢失消息

  • 发送方对群聊会话一致性hash到特定集群group ga中,然后由ga首位服务器s统一处理

    ga中机器如何按照接收时间标记顺序?

    通过比如向量时钟来同步集群中时间,然后通过该时间来标记接收顺序

    s什么时候将消息发送或者被拉取给群聊其他成员?

    • 等待一定时间,按照时间戳进行排序,进行发送

    • 询问ga其他机器是否有更早于已经收到的最晚消息,若没有就推送消息给群聊其他成员

    • 等待客户端拉取消息,将最新消息列表发送过去。若原本最先发送给集群的消息由于网络原因晚同步给s,那么s仍然以s接收到的时间为准

      也就是如果没有任何客户端主动拉取消息,那么s将根据收到消息的时间戳进行排序,但一旦拉取过了,就以s收到消息的时间为准

    如果s出现故障怎么办?

    若服务器x发现s心跳异常,则询问其他集群机器是否认为s异常,如果多数认为异常,标记s下线,交由新首位s1服务器处理(此时还是要求接收客户端进行幂等处理)

你可能感兴趣的:(distributed,网络,分布式)