怎么保证RabbitMQ和kafuka集群的高可用性?

471 阅读6分钟

rabbitMQ

有三种模式:单机模式,普通集群模式,镜像集群模式

RabbitMQ

的高可用性

RabbitMQ

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

rabbitmq

有三种模式:单机模式,普通集群模式,镜像集群模式

1

)单机模式

就是
demo
级别的,一般就是你本地启动了玩玩儿的,没人生产用单机模式

2

)普通集群模式

意思就是在多台机器上启动多个
rabbitmq
实例,每个机器启动一个。但是你创建的
queue
,只会放在一个
rabbtimq
实例上,但是每个实例都同步
queue
的元数据。完了你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从
queue
所在实例上拉取数据过来。

这种方式确实很麻烦,也不怎么好,没做到所谓的分布式,就是个普通集群。因为这导致你要么消费者每次随机连接一个实例然后拉取数据,要么固定连接那个
queue
所在实例消费数据,前者有数据拉取的开销,后者导致单实例性能瓶颈。

而且如果那个放
queue
的实例宕机了,会导致接下来其他实例就无法从那个实例拉取,如果你开启了消息持久化,让
rabbitmq
落地存储消息的话,消息不一定会丢,得等这个实例恢复了,然后才可以继续从这个
queue
拉取数据。

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

3

)镜像集群模式

这种模式,才是所谓的
rabbitmq
的高可用模式,跟普通集群模式不一样的是,你创建的
queue
,无论元数据还是
queue
里的消息都会存在于多个实例上,然后每次你写消息到
queue
的时候,都会自动把消息到多个实例的
queue
里进行消息同步。

这样的话,好处在于,你任何一个机器宕机了,没事儿,别的机器都可以用。坏处在于,第一,这个性能开销也太大了吧,消息同步所有机器,导致网络带宽压力和消耗很重!第二,这么玩儿,就没有扩展性可言了,如果某个
queue
负载很重,你加机器,新增的机器也包含了这个
queue
的所有数据,并没有办法线性扩展你的
queue

那么怎么开启这个镜像集群模式呢?我这里简单说一下,避免面试人家问你你不知道,其实很简单
rabbitmq
有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候可以要求数据同步到所有节点的,也可以要求就同步到指定数量的节点,然后你再次创建
queue
的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。


2
kafka
的高可用性

kafka

一个最基本的架构认识:多个
broker
组成,每个
broker
是一个节点;你创建一个
topic
,这个
topic
可以划分为多个
partition
,每个
partition
可以存在于不同的
broker
上,每个
partition
就放一部分数据。

这就是天然的分布式消息队列,就是说一个
topic
的数据,是分散放在多个机器上的,每个机器就放一部分数据。

实际上
rabbitmq
之类的,并不是分布式消息队列,他就是传统的消息队列,只不过提供了一些集群、
HA
的机制而已,因为无论怎么玩儿,
rabbitmq
一个
queue
的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个
queue
的完整数据。

kafka 0.8

以前,是没有
HA
机制的,就是任何一个
broker
宕机了,那个
broker
上的
partition
就废了,没法写也没法读,没有什么高可用性可言。

kafka 0.8

以后,提供了
HA
机制,就是
replica
副本机制。每个
partition
的数据都会同步到吉他机器上,形成自己的多个
replica
副本。然后所有
replica
会选举一个
leader
出来,那么生产和消费都跟这个
leader
打交道,然后其他
replica
就是
follower
。写的时候,
leader
会负责把数据同步到所有
follower
上去,读的时候就直接读
leader
上数据即可。只能读写
leader
?很简单,要是你可以随意读写每个
follower
,那么就要
care
数据一致性的问题,系统复杂度太高,很容易出问题。
kafka
会均匀的将一个
partition
的所有
replica
分布在不同的机器上,这样才可以提高容错性。

这么搞,就有所谓的高可用性了,因为如果某个
broker
宕机了,没事儿,那个
broker
上面的
partition
在其他机器上都有副本的,如果这上面有某个
partition
leader
,那么此时会重新选举一个新的
leader
出来,大家继续读写那个新的
leader
即可。这就有所谓的高可用性了。

写数据的时候,生产者就写
leader
,然后
leader
将数据落地写本地磁盘,接着其他
follower
自己主动从
leader
pull
数据。一旦所有
follower
同步好数据了,就会发送
ack
leader
leader
收到所有
follower
ack
之后,就会返回写成功的消息给生产者。(当然,这只是其中一种模式,还可以适当调整这个行为)

消费的时候,只会从
leader
去读,但是只有一个消息已经被所有
follower
都同步成功返回
ack
的时候,这个消息才会被消费者读到。

实际上这块机制,讲深了,是可以非常之深入的,但是我还是回到我们这个课程的主题和定位,聚焦面试,至少你听到这里大致明白了
kafka
是如何保证高可用机制的了,对吧?不至于一无所知,现场还能给面试官画画图。要遇上面试官确实是
kafka
高手,深挖了问,那你只能说不好意思,太深入的你没研究过。

但是大家一定要明白,这个事情是要权衡的,你现在是要快速突击常见面试题体系,而不是要深入学习
kafka
,要深入学习
kafka
,你是没那么多时间的。你只能确保,你之前也许压根儿不知道这块,但是现在你知道了,面试被问到,你大概可以说一说。然后很多其他的候选人,也许还不如你,没看过这个,被问到了压根儿答不出来,相比之下,你还能说点出来,大概就是这个意思了。