# 如果保证消息服务的高可用?
如何防止队列里的消息丢失呢?
下面让我们通过学习RabbitMQ,Kaffa的高可用策略,来了解如何构建一个高可用的消息服务。
## RabbitMQ
RabbitMQ的部署模式有3种,分别是单机,普通集群,镜像集群,下面进行逐一解释。
* **单机**
只有一台RabbitMQ实例提供服务,没有高可用性可言
* **普通集群**
由分别部署在各自服务器的多台RabbitMQ实例提供服务,生产者创建的queue和队列数据会被保存在某一个实例中,剩下的实例只会保存该queue的元数据。
当生产者向实例写入数据的时候,其中一台RabbitMQ实例会保存queue和队列数据,剩下的实例会从该实例pull该queue的元数据并保存。
当消费者读取指定的queue时,如果连接的实例非保存了原始数据的实例,需要从原始实例拉取queue返回客户端。
如果queue所在的实例宕机,在开启了数据持久化的情况下,可以从磁盘重新拉取数据。
* **镜像集群**
由分别部署在各自服务器的多台RabbitMQ实例提供服务。生产创建的queue和队列数据会被保存在多个实例中。
生产者写入消息时,包括queue和队列数据,除了保存在当前实例中,还会被同步到其他多个实例中。
### 小结
普通集群在高可用上有欠缺。
镜像集群保证了任意一台实例宕机,另一台实例能够提供同样的服务
但镜像集群也带来了一定的副作用,每一条消息需要在不同的实例之间同步,消耗大量带宽。同时带来了扩展性问题,新添加的实例会同步其他实例的数据,导致了实例添加成功但是没有带来空间的扩容。
RabbitMQ提供了一个控制台,支持对同步数据的实例数量自定义。
## Kafka
* 基本架构
每台实例作为一个broker节点组成了Kafka的基本架构。一个topic被分割成多个partition分别保存在不同的broker节点。
* 原理
0.8版本之后的Kafka才提供的HA机制,每个partition上的数据被复制多份保存于多个broker节点中,同系列的partitoin被抽象为一个replica副本(小队)。每个小队会推选出一个leader(队长),剩下的都是follower(队员)。partition的数据由队长向生产者和消费者提供服务。
* 生产者写入
生产者向topic下的partition写入数据时,replica副本完成了5个步骤
1. 数据写入leader
2. leader将数据持久化到磁盘
3. follower从leader pull数据
4. follower返回leader ack
5. leader返回生产者写入成功
* 消费者消费
消费状态同步到follower并返回ack之后,该消息才会被消费者消费
## 总结
RabbitMQ保存消息到指定的实例,另外若干个实例拷贝该实例数据来保证数据的备份,服务的高可用。
Kafka采用了分布式架构,根据消息归属于不同的partition,消息被保存到不同的实例。通过replica副本来保证服务的高可用。