当前位置:首页 > 短网址资讯

IM 消息可靠性及一致性的解决方案

www.ft12.com9年前 (2017-08-01)短网址资讯2204

即时聊天(IM)系统需要解决消息可靠性及消息一致性问题。

消息可靠性,简单来说就是不丢消息,会话一方发送消息,消息成功到达对方并正确显示;消息一致性,包括发送一方消息一致及会话双方消息一致,要求消息不重复,不乱序。

消息发送实现过程

消息发送一般的实现过程可以分为两个阶段:发送方发送消息,服务端接收,返回消息 ACK 给发送方;服务端将消息推送到接收方。判断消息发送是否成功主要依据第一阶段,即服务器是否接受到消息,消息状态可以分为三类:正在发送、发送成功、发送失败。其节点分别是:

1. 正在发送:发送方触发发送事件开始,到收到服务端返回消息对应 ACK 之前;

2. 发送成功:发送方收到消息对应 ACK 回复;

3. 发送失败:超过一定重发次数,未收到消息对应 ACK 回复。

消息发送流程图:

消息可靠性

重发机制

保证消息发送第一阶段消息成功发送的方法是设立重发机制,依据一定时长内是否收到消息对应 ACK,判断消息是否要重发,如果超过预设时长,就重新发送。当重发次数超过预设次数,就不再重发,判定该消息发送失败,修改消息发送状态。

会话记录检查

消息发送第二阶段服务端推送消息到接收方,如果连接断开,会丢失消息,所以要保证消息完整,就需要在建立连接后,根据上一条消息(已经 ACK)时间戳,获取会话记录,一次返回一段时间内所有消息。

另一种保证方法是加入定时轮询,检查消息完整性。

建立连接流程图:

两个问题

消息重发、会话记录检查需要考虑两个问题:消息是否会重复发送,消息顺序是否会被打乱。举两个例子:

1. 消息重发,如果丢消息的点在消息达到服务端之前,服务端并没有收到消息,发送方重新发送丢失消息,服务端接收成功,不会产生两条相同消息;而如果服务端接收到消息,返回 ACK 丢失,这时再发送一次相同消息,就可能造成消息重复。

2. 消息顺序,如果发送方连发三条消息,第一、第三条成功被服务端接收,第二条丢了,那第三条消息是否会被记录?如果这时第二条消息达到服务端,其顺序是在第三条时间之前还是之后(服务端一般都会给记录打一个时间戳)?

消息一致性

使用 uuid 消息去重

对于消息重发问题,可以给每条消息增加属性 uuid 作为消息唯一标识,重发消息 uuid 不变,前端根据 uuid 去重。

使用向量时钟进行消息排序

对于消息排序问题,因为在聊天中,消息的顺序对于发送方的表述有重要的影响,消息不完整或顺序颠倒都可能造成语意不连贯,甚至曲解。所以需要保证发送方发送消息顺序,而会话双方消息排序需要考虑实际情况。

在一般的认知里,状态是正在发送的消息,应该还没有被对方看到,只有发送成功的消息,才会被对方看到。但在实现中,消息发送成功是以服务器接收消息并返回 ACK 成功为判断依据,而不是被对方接收到。

那么就会出现这样一个问题,如果一条消息状态是正在发送,此时收到一条消息,那么收到的消息是在正在发送的消息之前还是之后?

这是一个上下文关系,关键问题是发送方是以哪条所见消息为依据发送消息的。

这里提供一种思路,借鉴分布式系统中的向量时钟算法。先简单描述向量时钟算法:

向量时钟算法用于在分布式系统中生成事件偏序关系,并纠正因果关系。一个系统包含 N 个节点,每个节点产生的消息体中包含该节点的逻辑时钟,整体系统的向量时钟由 N 维逻辑时钟组成,并在每个节点产生的消息体中传递。

向量时钟算法的具体实现:

1. 初始状态,向量值为 0;

2. 每次节点处理完节点事件,该节点时钟加一;

3. 每次节点发送消息,将包含自身时钟的系统向量时钟一起发送;

4. 每次节点收到消息,更新系统向量时钟,该节点时钟加一,其他节点对比每个节点本地保留的向量时钟的值和消息体中向量时钟的值,取最大值。

5. 节点同时收到多条消息,判断接收消息的向量时钟之间是否存在偏序关系

1. 如果存在偏序关系,则合并向量时钟,取偏序较大的向量时钟;

2. 如果不存在偏序关系,则不能合并。

  • 偏序关系:如果 A 向量中的每一维都大于等于 B 向量,则 A、B 之间存在偏序关系,否则不存在偏序关系。

对于消息排序,其实就是处理消息的上下文语境,决定消息之间的因果关系。参考向量时钟算法,假设有 N 个消息会话方,系统的向量时钟由 N 维时钟组成,向量时钟在各方发送的消息体中传递,并依据向量时钟排序,具体实现:

1. 系统向量时钟设为 (0, 0, …, N);

2. 节点发送消息,更新系统向量时钟,该节点时钟加一,其他节点不变;

3. 节点接收消息,更新系统向量时钟,该节点时钟加一;其他节点对比每个节点本地保留的向量时钟的值和消息中向量时钟的值,取最大值。

4. 依据消息体内系统向量时钟的偏序关系决定消息顺序:

1. 如果可以确定偏序关系,则根据偏序关系由小到大显示;

2. 如果多条消息不能确定偏序关系,则按照自然顺序(接收到的顺序)显示。

向量时钟在理论上可以解决大部分消息一致性的问题,但在实现中还需要考虑实际使用时的体验,这其中最需要关注的问题是:是否要强制排序,或者说,如果实际显示顺序和向量时钟之间的偏序关系不一致,是否要移动消息之间的顺序。

举个例子,在一个有多人的会话中,如果有一方网速特别慢,收不到消息,也发不出消息。在他看到的最后的消息之后,其他人已经开始新的话题,这时他关于上一个话题的消息终于发送成功,并被其他人收到,此时就存在这样一个问题:

这条关于上一个话题的消息是显示在最后,还是移到较早时间?如果显示在最后,但消息内容和目前的话题不相关,其他人可能会感到莫名其妙;如果把消息移到较早时间,那么这条消息可能不会被其他人看到,或者看到前面多了一条消息,会有种突兀的感觉。

IM 的场景很多,也很复杂,更多的时候需要从产品角度考虑问题。对于消息是否需要排序的问题,这里只提出一个比较通用的方案:建议会话中不强制排序,会话历史记录中按照向量时钟的偏序关系进行排序。

小结

对于 IM 系统消息可靠性及一致性问题,通过消息重发机制保证消息成功被服务端接收,通过会话记录检查保证收取消息完整,从而保证整个消息发送过程的可靠性;使用 uuid 消息去重,参考向量时钟算法进行消息排序,为保证消息一致性提供一种解决方案。

扫描二维码推送至手机访问。

版权声明:本文由短链接发布,如需转载请注明出处。

本文链接:https://www.ft12.com/article_368.html

分享给朋友:

相关文章

PHP编程需要掌握的20个要点,能极大提高效率

PHP编程需要掌握的20个要点,能极大提高效率

[摘要] 用单引号取代双引号来包括字符串,这样做会更快一些。由于PHP会在双引号包抄的字符串中征采变量,单引号则 不会,留意:只要echo能这么做,它是一种能够把多个字符串看成参数的“函数”用单引号取代双引号来包括字符串,这样做会更快一些。…

在线教育企业7成亏损,15%濒临倒闭,你如何突围?

在线教育企业7成亏损,15%濒临倒闭,你如何突围?

[ 亿欧导读 ] 四月暮春,又到了一年一度在线教育公司交作业的时期,无论是自己晒成绩,还是第三方机构出评估,我们看到报表里的在线教育行业都是欣欣向荣、前景喜人,但真实情况如何?在线教育市场规模增幅迅猛,2019年将达2692.6亿…

勒索病毒“永恒之蓝”大爆发

勒索病毒“永恒之蓝”大爆发

2017年5月12日20时左右,新型“蠕虫”式勒索病毒“WannaCry”爆发。截至目前,该病毒已经席卷包括中国、美国、俄罗斯及欧洲在内的100多个国家。我国部分高校内网、大型企业内网和政府机构专网遭受攻击,被感染的组织和机构已经覆盖了几乎…

消费者变成“智”人,供应链要变成“人工”智能

消费者变成“智”人,供应链要变成“人工”智能

[ ft12短网址导读 ] 智能供应链包含:①智能预测;②智能商品;③智能定价;④智能库存;⑤科学地分配订单生产路径及快递安排;⑥基于模式识别等技术的风险控制系统,及时预警订单的风险级别等。图片来自“123rf.com.cn”【编…

短网址和二维码在共享单车扫码开车上的应用

如果我问大家现在城市和以前的城市最大的变化是什么,估计大部分人会不假思索的想到共享单车。目前共享单车正以不可阻挡之势席卷全国,大街上以及城市的每一个角落正在被ofo、摩拜单车、小鸣单车等等所占领。共享单车这项期初并不被看好的项目,正在逐渐改…

短网址的正确使用方式

短网址毋庸置疑是一个伟大的互联网产物,什么行业都能用的到。今天去莱茵培训,一路上都是靠着短链接和二维码指引过去的,真的是太方便了。首先,高铁票上的短链接指引着我去了上海火车站,很快,从安亭到上海火车站只花了不到15分钟,简直不可思议,安亭人…

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。