【Distributed System】消息队列 - 如何保证高可用

Posted by 西维蜀黍 on 2019-08-01, Last Modified on 2023-02-16

怎么保证MQ的高可用特性?

使用了MQ之后,我们肯定是希望MQ有高可用特性,因为不可能接受机器宕机了,就无法收发消息的情况。

这一块我们也是基于RabbitMQ这种经典的MQ来说明一下:

RabbitMQ是比较有代表性的,因为是基于主从做高可用性的,我们就以他为例子讲解第一种MQ的高可用性怎么实现。

RabbitMQ有三种模式:

  • 单机模式
  • 普通集群模式
  • 镜像集群模式

单机模式

单机模式就是demo级别的,就是说只有一台机器部署了一个RabbitMQ程序。

这个会存在单点问题,宕机就玩完了,没什么高可用性可言。一般就是你本地启动了玩玩儿的,没人生产用单机模式。

普通集群模式

这个模式的意思就是在多台机器上启动多个RabbitMQ实例。类似的master-slave模式一样。

但是创建的queue,只会放在一个master rabbtimq实例上,其他实例都同步那个接收消息的RabbitMQ元数据。

在消费消息的时候,如果你连接到的RabbitMQ实例不是存放Queue数据的实例,这个时候RabbitMQ就会从存放Queue数据的实例上拉去数据,然后返回给客户端。

总的来说,这种方式有点麻烦,没有做到真正的分布式,每次消费者连接一个实例后拉取数据,如果连接到不是存放queue数据的实例,这个时候会造成额外的性能开销。如果从放Queue的实例拉取,会导致单实例性能瓶颈。

如果放queue的实例宕机了,会导致其他实例无法拉取数据,这个集群都无法消费消息了,没有做到真正的高可用。

所以这个事儿就比较尴尬了,这就没有什么所谓的高可用性可言了,这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个queue的读写操作。

镜像集群模式

镜像集群模式才是真正的RabbitMQ的高可用模式,跟普通集群模式不一样的是:创建的queue无论元数据还是queue里的消息都会存在于多个实例上,

每次写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。

这样的话任何一个机器宕机了别的实例都可以用提供服务,这样就做到了真正的高可用了。

但是也存在着不好之处:

  • 性能开销过高,消息需要同步所有机器,会导致网络带宽压力和消耗很重
  • 扩展性低:无法解决某个queue数据量特别大的情况,导致queue无法线性拓展。

就算加了机器,那个机器也会包含queue的所有数据,queue的数据没有做到分布式存储。

对于RabbitMQ的高可用一般的做法都是开启镜像集群模式,这样起码来说做到了高可用,一个节点宕机了,其他节点可以继续提供服务。

Reference