RabbitMQ高可用性
RabbitMQ訊息應答
執行一個任務可能需要花費幾秒鐘,你可能會擔心如果一個消費者在執行任務過程中掛掉了。一旦RabbitMQ將訊息分發給了消費者,就會從記憶體中刪除。在這種情況下,如果正在執行任務的消費者宕機,會丟失正在處理的訊息和分發給這個消費者但尚未處理的訊息。
但是,我們不想丟失任何任務,如果有一個消費者掛掉了,那麼我們應該將分發給它的任務交付給另一個消費者去處理。
為了確保訊息不會丟失,RabbitMQ支援訊息應答。消費者傳送一個訊息應答,告訴RabbitMQ這個訊息已經接收並且處理完畢了。RabbitMQ就可以刪除它了。
如果一個消費者掛掉卻沒有傳送應答,RabbitMQ會理解為這個訊息沒有處理完全,然後交給另一個消費者去重新處理。這樣,你就可以確認即使消費者偶爾掛掉也不會丟失任何訊息了。
RabbitMQ叢集方案
設計叢集的目的:
- 允許消費者和生產者在RabbitMQ節點崩潰的情況下繼續執行
- 通過增加更多的節點來擴充套件訊息通訊的吞吐量
RabbitMQ可以通過三種方法來部署分散式集群系統,分別是:cluster(叢集),federation(聯盟),shovel
叢集通過連線多個機器組成單個邏輯中間伺服器。機器之間通訊要藉助於Erlang的訊息傳輸,要求叢集中所有節點必須有相同的Erlang cookie;節點之間的網路必須是可靠的,且執行相同版本的RabbitMQ和Erlang。
虛擬主機、交換機、使用者資訊和許可權會自動映象到叢集中各個節點。佇列可能位於單個節點或映象到多個節點。連線到任意節點的客戶端能夠看到叢集中所有佇列,即使該佇列不位於連線節點上。通常可以使用叢集來提高可靠性和吞吐量,前提是在分佈同一個區域內的機器,不支援網路分段。聯盟允許單臺伺服器上的交換機或佇列接收發布到另一臺伺服器上交換機或佇列的訊息,可以是單獨機器或叢集。伺服器之間通過AMQP協議通訊,因此兩個聯盟交換機或聯盟佇列要求設定相應的使用者許可權。
聯盟交換機之間由單向點對點連結關聯,預設訊息只會由聯盟連結轉發一次,但允許有更復雜的路由拓撲來提高轉發次數。訊息也可以不進行轉發;如果訊息到達聯盟交換機之後不會路由到佇列,那麼它再也不會被轉發。
聯盟佇列類似於單向點對點連線,訊息會在聯盟佇列之間轉發任意次,直到被消費者接受。
通常使用聯盟來連線internet上的中間伺服器,用作訂閱分發訊息或工作佇列。shovel
連線方式與聯盟的連線方式類似,但它工作在更低層次。shovel接受佇列上的訊息,轉發到另一臺伺服器上的交換機。
shovel和聯盟類似,但它比聯盟提供更多控制。
聯盟/shovel vs 叢集:
1)前者中間伺服器邏輯分離,後者組成一個邏輯中間伺服器;
2)前者可以執行不同版本RabbitMQ和Erlang,後者要求RabbitMQ和Erlang的版本保持一致;
3)前者可以分佈在WAN上,採用AMQP協議通訊,要求設定許可權,後者必須分佈在LAN上,結合Erlang內部節點通訊,要求有相同的Erlang cookie;
4)前者的拓撲結構可自行設計,連結可以單向或雙向,後者要求節點之間必須保持雙向連結;
5)前者遵循CAP理論的可用性和分割槽容錯性,後者遵循CAP理論的一致性和可用性(可選擇一致性和分佈容錯性);
6)前者伺服器中的交換機可以選擇聯盟或本地,後者孤注一擲;
7)前者客戶端只能看到所連線伺服器上的佇列,後者客戶端可以看到所有節點的佇列。
在容災與可用性方面,RabbitMQ提供了可持久化的佇列。能夠在佇列服務崩潰的時候,將未處理的訊息持久化到磁碟上。為了避免因為傳送訊息到寫入訊息之間的延遲導致資訊丟失,RabbitMQ引入了Publisher Confirm機制以確保訊息被真正地寫入到磁碟中。它對Cluster的支援提供了Active/Passive與Active/Active兩種模式。例如,在Active/Passive模式下,一旦一個節點失敗,Passive節點就會馬上被啟用,並迅速替代失敗的Active節點,承擔起訊息傳遞的職責。