天天看點

RabbitMQ可用性和可靠性分析

本文分析一下rabbitmq的可用性和可靠性。分析一下rabbitmq如何在可用性和可靠性之間進行權衡的。

1. 基本概念。

首先,介紹幾個rabbitmq的重要的基本概念。這些概念是了解rabbitmq的可用性和可靠性的基礎。

鏡像隊列(mirrored queue)

rabbitmq叢集的隊列(queue)在預設的情況下隻存在單一節點(node)上。但是,我們也可以把隊列配置成同時存在在多個節點上,也就是說隊列可以被鏡像到多個節點上。釋出(publish)到鏡像隊列上的消息(message)會被複制(replicated)到說有的節點上。一個鏡像隊列包含一個主(master)和多個從(slave)。

非同步的slave (unsynchronised slave)

在很多其他産品中,同步(synchronation)這個詞是和異步(asynchronation)對立使用。但在rabbitmq中,同步(synchronised)這個詞是和非同步(unsynchronised)這個詞對立的。這有什麼差別那?在rabbitmq中同步(synchronised)是用來描述master和slave之間的資料狀态是否一緻的。如果slave包含master中的所有message,則這個slave是synchronised,如果這個slave并沒有包含所有master中的message,則這個slave是unsynchronised。同步與異步的對立使用的典型的例子是mysql的主從資料複制,資料複制過程可以分為同步複制和異步複制。

在什麼情況下會出現unsynchronised slave?

當一個新slave加入到一個鏡像隊列時,這時這個新slave是空的,而master中這時可能包含之前接收到的消息。假設這時master包含了5條消息,這是第6條消息被添加到這個鏡像隊列中,這個新slave會從這個第6條消息開始接收。這時這個slave就是unsynchronised slave。随着前5條消息從鏡像隊列中被消費掉(consumed), 這個slave變成了synchronised。

另外一種情況,slave 重新加入(rejoin) 到鏡像隊列時,也會出現非同步的情況。一個slave出于很多情況會重新加入鏡像隊列,網絡分區(network partition)就可能導緻這種情況。一個slave要重新加入鏡像隊列之前,slave可能已經接收了一些消息,它要重新加入鏡像隊列,就要清空自己之前已經接收的所有消息,好像自己是第一次加入隊列一樣。

選主方式

由于rabbitmq的slave加入和重新加入隊列的方式,我們得出一個結論,越早加入隊列的slave,越有更大的機會是同步狀态的,是以rabbitmq通過這種方式選主:但master因為某種原因消失時,最老的slave被提升成master。

2. rabbitmq的可用性(availablity)和資料可靠性(reliability)

接下來,我們分析一下rabbitmq的可用性(availablity)和資料可靠性(reliability)。rabbitmq通過參數配置的方式,在可用性(availablity)和資料可靠性(reliability)做出了一定的權衡。下面我們來看看這些參數。

參數ha-sync-mode

鏡像隊列有一個配置參數ha-sync-mode,這個參數有2中取值:automatic, manual。

manual是預設值。如果鏡像隊列被設定成munual,當一個slave加入和重新加入隊列時的行為,就是我們上面描述的行為,之是以叫manual,就是我們可以通過指令行手工(manually)進行同步。指令如下:

rabbitmqctl sync_queue name

如果鏡像隊列被設定成automatic,當一個新slave加入時,slave會自動同步master中的所有消息,直到所有消息被同步完成之前,所有的操作都會被阻塞(blocking)。

這個參數是可用性和可靠性的一個平衡,manual不保證資料可靠性,在某些情況會出現丢消息的可能,但是保證了隊列的可用性。automatic提高了資料的可靠性,但是當有新slave加入時,可能會出現隊列的暫時不可用。

參數ha-promote-on-shutdown

鏡像隊列的另外一個參數ha-promote-on-shutdown,也在可用性和可靠性之間做了一個平衡。ha-promote-on-shutdown有2個取值:when-synced,always。預設是when-synced。ha-promote-on-shutdown是用來控制選主的行為的。

當取值為when-synced時,在可控的master關閉時(比如停止rabbitmq服務或者關閉作業系統),rabbitmq會拒絕故障恢複(fail over)到一個非同步slave,也即拒絕把一個非同步的slave提升成新的master。隻有在非可控的master關閉時(比如server crash, 斷網),才會故障恢複到一個非同步的slave。

當取值為always時,則在所有情況下,都不會拒絕故障恢複到非同步的slave。

很明顯,這個參數也是平衡可用性和可靠性的,當when-synced,可靠性更好,可用性降低了,因為如果所有的slave都是非同步狀态,那就沒有符合條件的slave可以被提升成master,這時隊列就處在不可用狀态。