本文从高可用的角度观察一下 RabbitMQ、Kafka、RocketMQ,看看它们各自的实现思路。
1. RabbitMQ
RabbitMQ 有 3 种部署模式:
- 单机模式
- 普通集群模式
- 镜像集群模式
单机模式与高可用完全没关系,咱就不说了,直接看看这2种集群模式。
1.1 普通集群模式
某一个 Queue 是在集群中的某一个 Broker 上,各个 Broker 会同步元数据,但不会同步 Queue 的消息数据。
如果某一个 Broker 故障了,其中的 Queue 便无法使用。如果消息没有配置消息持久化,则消息丢失。
可以看到,这种方式并没有实现高可用,只是扩展性比较好,扩充 Broker 可以容纳更多的 Queue,提高吞吐量。
1.2 镜像集群模式
一个 Broker 中 Queue 的元数据和消息数据都会同步到其他 Broker 上,就是做了全量备份,所以称为 “镜像模式”。
实现了高可用,如果一个 Broker 故障了,没关系,可以使用其他 Broker 继续工作,消息数据不会丢失。
可用性上去了,但扩展性没有了。
一个 Queue 的数据是全量存在 Broker 中的,所以 Queue 的消息容量、消息处理能力,都受限于 Broker。
普通集群模式 没有达到高可用,扩展性较好。
镜像集群模式 实现了高可用,但扩展性差。
2. Kafka
Kafka 把 Topic(主题/队列)分为了多个 Partition(分区),Topic 只是逻辑概念,Partition 才是实际的消息存储单元。
一个 Topic 的多个 Partition 分散在多个 Broker 中,每个 Partition 存放 Topic 的一部分数据。
有了 Partition 之后,Topic 就具有了极强的扩展性,可以指定 N 个 Partition。
可以为 Partition 指定多个“副本”,分散在不同的 Broker,从而实现其高可用。
当某个 Broker 故障的时候,其中存放的 Partition 不可用,但没有关系,可以使用其他 Broker 上的副本。
Partition 的多个副本分为两种角色,Leader 和 Follower。
Leader 是由 Kafka 选举出来的,负责处理消息的读写。Leader 收到新消息后,会同步给 Follower。
Follower 的作用是候选人,当 Leader 出事儿之后,Kafka 会从 Follower 中选举出新的 Leader。
可以配置消息写入完成的标准:
- 写入 Leader 既可 -- 速度快,但可能会有消息丢失,例如在同步到 Follower 之前 Broker 故障了,则消息丢失。
- Follower 同步完成之后才算写入成功 -- 消息可靠性极高,但影响写入速度。
3. RocketMQ
这是 RocketMQ 的官方结构图,左右是 Producer 和 Consumer,中间是 RocketMQ,分为两个部分:
- NameServer 集群 -- 存放元数据
- Broker 集群 -- 存放队列数据
这两部分都需要保证高可用。
NameServer 是独立运行的,保存着集群完整的集群元数据,例如路由信息、Broker信息、数据信息。
为了保证其高可用,可以运行多个 NameServer,之间完整的同步数据即可。
这样只要有一个 NameServer 是可用的,就不会影响集群的正常工作。
Broker 集群的部署方式可以分为 3 种。
- 多 Master
部署多个 Broker,角色都是 Master,Topic 的数据会分散存储在这些 Broker 中。
单个 Master 故障会导致其中数据无法使用,需要等待修复。
如果想保障数据的可靠性,可以使用【RAID10 同步刷盘】机制。
- 多 Master 多 Slave
为 Master 配置了 Slave,Master 会把数据同步到 Slave。
当 Master 故障之后,可以用 Slave 顶上去,数据和服务都不影响,但会有短暂的停顿,需要修改配置并重启才能完成切换动作。
数据同步的方式分为:
1)异步 -- Master 写入完成即可,异步同步给 Slave。写入速度快,但同步会有延迟,可能会丢数据。
2)同步 -- Master 与 Slave 都写入之后才算成功。不会丢消息,但写入速度降低。
- Dledger Group
Dledger 模式要求为 Master 配置 2 个 Slave,3 者组成一个 Dledger Group。
Dledger 也是 Master-Slave 同步的方式,好处在于可以实现自动选举 Master,自动切换。
当 Master 故障的时候,RocketMQ 可以从组内选出一个新的 Master,完成自动切换,这样更进一步提高了集群的可用性。
最后小结一下。