设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 手机 数据 公司
当前位置: 首页 > 服务器 > 安全 > 正文

一篇文了解分布式队列编程:从模型、实战到优化(6)

发布时间:2021-01-08 08:29 所属栏目:53 来源:网络整理
导读:高可用性的消息中间件应该具备如下特征: 消息中间件代理服务器(Broker)具有主从备份.即当一台代理服务宕机之后,备用服务器能接管相关的服务. 消息中间件中缓存的消息是否有备份、并持久化. 根据CAP理论,高可用、高

高可用性的消息中间件应该具备如下特征:

  • 消息中间件代理服务器(Broker)具有主从备份.即当一台代理服务宕机之后,备用服务器能接管相关的服务.
  • 消息中间件中缓存的消息是否有备份、并持久化.
  • 根据CAP理论,高可用、高一致性以及网络分裂不可兼得.根据作者的观察,大部分的消息中间件在面临网络分裂的情况下下,都很难保证数据的一致性以及可用性. 很多消息中间件都会提供一些可配置策略,让使用者在可用性和一致性之间做权衡.

高可靠的消息中间件应该确保从发送者接收到的消息不会丢失.中间件代理服务器的宕机并不是小概率事件,所以保存在内存中的消息很容易发生丢失.大部分的消息中间件都依赖于消息的持久化去降低消息丢失损失,即将接收到的消息写入磁盘.即使提供持久化,仍有两个问题需要考虑:

  • 磁盘损坏问题.长时间来看,磁盘出问题的概率仍然存在.
  • 性能问题.与操作内存相比,磁盘I/O的操作性能要慢几个数量级.频繁持久化不仅会增加响应时间,也会降低吞吐量.
  • 解决这两个问题的一个解决方案就是:多机确认,定期持久化.即消息被缓存在多台机器的内存中,只有每台机器都确认收到消息,才跟发送者确认(很多消息中间件都会提供相应的配置选项,让用户设置最少需要多少台机器接收到消息).由于多台独立机器同时出故障的概率遵循乘法法则,指数级降低,这会大大提高消息中间件的可靠性.

确认机制本质上是通讯的握手机制(Handshaking).如果没有该机制,消息在传输过程中丢失将不会被发现.高敏感的消息要求选取具备确认机制的消息中间件.当然如果没有接收到消息中间件确认完成的指令,应用程序需要决定如何处理.典型的做法有两个:

  • 多次重试.
  • 暂存到本地磁盘或其它持久化媒介.
客户端接口所支持语言

采用现存消息中间件就意味着避免重复造轮子.如果某个消息中间件未能提供对应语言的客户端接口,则意味着极大的成本和兼容性问题.

投递策略(Delivery policies)

投递策略指的是一个消息会被发送几次.主要包含三种策略:最多一次(At most Once )、最少一次(At least Once)、仅有一次(Exactly Once).

在实际应用中,只考虑消息中间件的投递策略并不能保证业务的投递策略,因为接收者在确认收到消息和处理完消息并持久化之间存在一个时间窗口.例如,即使消息中间件保证仅有一次(Exactly Once),如果接收者先确认消息,在持久化之前宕机,则该消息并未被处理.

从应用的角度,这就是最多一次(At most Once).反之,接收者先处理消息并完成持久化,但在确认之前宕机,消息就要被再次发送,这就是最少一次(At least Once). 如果消息投递策略非常重要,应用程序自身也需要仔细设计.

消费者优化

消费者是分布式队列编程中真正的数据处理方,数据处理方最常见的挑战包括:有序性、串行化(Serializability)、频次控制、完整性和一致性等.

挑战

有序性

在很多场景下,如何保证队列信息的有序处理是一个棘手的问题.如下图,假定分布式队列保证请求严格有序,请求ri2和ri1都是针对同一数据记录的不同状态,ri2的状态比ri1的状态新.T1、T2、T3和T4代表各个操作发生的时间,并且 T1 < T2 < T3 < T4(”<“代表早于).

采用多消费者架构,这两条记录被两个消费者(Consumer1和Consumer2)处理后更新到数据库里面.Consumer1虽然先读取ri1但是却后写入数据库,这就导致,新的状态被老的状态覆盖,所以多消费者不保证数据的有序性.

串行化

很多场景下,串行化是数据处理的一个基本需求,这是保证数据完整性、可恢复性、事务原子性等的基础.为了在并行计算系统里实现串行化,一系列的相关理论和实践算法被提出.对于分布式队列编程架构,要在在多台消费者实现串行化非常复杂,无异于重复造轮子.

频次控制

有时候,消费者的消费频次需要被控制,可能的原因包括:

  • 费用问题.如果每次消费所引起的操作都需要收费,而同一个请求消息在队列中保存多份,不进行频次控制,就会导致无谓的浪费.
  • 性能问题.每次消费可能会引起对其他服务的调用,被调用服务希望对调用量有所控制,对同一个请求消息的多次访问就需要有所控制.
完整性和一致性

完整性和一致性是所有多线程和多进程的代码都面临的问题.在多线程或者多进程的系统中考虑完整性和一致性往往会大大地增加代码的复杂度和系统出错的概率.

单例服务优化

几乎所有串行化理论真正解决的问题只有一个:性能. 所以,在性能允许的前提下,对于消费者角色,建议采用单实例部署.通过单实例部署,有序性、串行化、完整性和一致性问题自动获得了解决.另外,单实例部署的消费者拥有全部所需信息,它可以在频次控制上采取很多优化策略.

天下没有免费的午餐.同样,单实例部署并非没有代价,它意味着系统可用性的降低,很多时候,这是无法接受的.解决可用性问题的最直接的思路就是冗余(Redundancy).最常用的冗余方案是Master-slave架构,不过大部分的Master-slave架构都是Active/active模式,即主从服务器都提供服务.

例如,数据库的Master-slave架构就是主从服务器都提供读服务,只有主服务器提供写服务.大部分基于负载均衡设计的Master-slave集群中,主服务器和从服务器同时提供相同的服务.这显然不满足单例服务优化需求.

有序性和串行化需要Active/passive架构,即在某一时刻只有主实例提供服务,其他的从服务等待主实例失效.这是典型的领导人选举架构,即只有获得领导权的实例才能充当实际消费者,其他实例都在等待下一次选举.采用领导人选举的Active/passive架构可以大大缓解纯粹的单实例部署所带来的可用性问题.

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读