# 如果保證消息服務的高可用?
如何防止隊列里的消息丟失呢?
下面讓我們通過學習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副本來保證服務的高可用。