RabbitMQ高可用方案總結


RabbitMQ的集群方案有以下幾種: 
1.普通的集群 
exchange,buindling再所有的節點上都會保存一份,但是queue只會存儲在其中的一個節點上,但是所有的節點都會存儲一份queue的meta信息。因為這樣有兩個好處: 
1)存儲空間。如果每一個節點上都有全部的消息,有多少個節點就會有多少個消息總量的copy。加入一個隊列的消息占用的空間是1G,那么三個節點就是3G 
2) 性能。消息需要在節點之間傳輸會有很大的網絡開銷。如果消息設置了durable即持久化,還會增加很大的磁盤負載 
隊列存儲的節點取決於,創建隊列的客戶端當時所連接的節點。如果生產者連接的是另外一個節點,將會把消息轉發到存儲該隊列的節點上。如果消費者連接了非存儲隊列的節點取數據,者從存儲消息的節點拉去數據。所以: 
1)創建隊列都連到了一個節點上,所有的隊列都存儲在一個節點上。 
2)存消息的節點掛掉了,consumer只能等到節點恢復后才能讀到消息。 
3)設A,B節點,queue數據在A上:可以向A或B生產或消費消息。但是一旦往B生產消息時A掛了,client是不會收到任何錯誤信息的並可以繼續發送,而實際上消息是被丟棄了。一旦此時client掛了后在連接B會報節點A不存在而失敗。在B讀也是類似的,在client批量取到的數據讀完之前是不會感知A有沒有掛掉,等到讀取下一批數據時一旦A掛掉會報錯。 
所以這種集群方法的特點是: 
1) 高吞吐量 
2)非高可用 

2.鏡像模式 
鏡像模式和普通模式的區別就是,隊列的數據都鏡像了一份到所有的節點上。這樣任何一個節點失效,不會影響整個集群的使用。 
在實現上,mirror queue內部有一套選舉算法,會選出一個master,和若干個slaver。master和slaver 通過相互間不斷發送心跳來檢查是否連接斷開。可以通過指定net_ticktime來控制心跳檢查頻率。注意一個單位時間net_ticktime實際上做了4次交互,故當超過net_ticktime (± 25%) 秒沒有響應的話則認為節點掛掉。另外注意修改net_ticktime時需要所有節點都一致。 
配置舉例: 

        {rabbit, [{tcp_listeners, [5672]}]}, 
        {kernel, [{net_ticktime,  120}]} 
]. 
consumer,任意連接一個節點,若連上的不是master,請求會轉發給master,為了保證消息的可靠性,consumer回復ack給master后,master刪除消息並廣播所有的slaver去刪除。 
publisher ,任意連接一個節點,若連上的不是master,則轉發給master,由master存儲並轉發給其他的slaver存儲。 
如果master掛掉,則從slaver中選擇消息隊列最長的為master,在這種情況下可以存在消息未同步給ack消息未同步的情況,會造成消息重發(默認是異步同步的)。總共有以下幾件事情發生: 

1)1個最老的(隊列最長的)的slaver提升為master,如果沒有一個slaver是和master同步的則會造成消息丟失。 
2) 要提升為master的slaver會認為以前所有連接掛掉的master的消費者都斷開了連接。那么存在clinet發送了ack的消息單還在路上是master掛掉的情況,或者master收到了ack但是在廣播給slaver的時候master掛掉的情況,所以新的master別無選擇,只能認為消息沒有被確認。他會requeue他認為沒有ack的消息。那么client可能就收到了重復的消息,並要再次發送ack。 

3)從鏡像隊列中消費的client支持了consumer Cancellation通知的,將收到通知並訂閱的mirrored-queue被取消了,這是因為該mirrored-queue 升級成了master,這是client需要重現去找mirrored-queue上消費,這樣就避免了client繼續發送ack到老的掛掉的master上。避免收到新的master發送的相同的消息。 
4)如果noAck=true,且在mirrored-queue上消費,那么在切換時由於服務器是先ack然后發送到noAck=true的消費者,這時連接斷開可能導致該數據丟失 

如果slaver掛掉,則集群的節點狀態沒有任何變化。只要client沒有連到這個節點上,也不會給client發送失敗的通知。在檢測到slaver掛掉的期間publish消息會有延遲。如果配置了高可用策略是自動同步,當slaver起來后,隊列中有大量的消息需要同步,將會整個集群阻塞長時間的不能讀寫直到同步結束。 
這兩個掛掉的情況都需要客戶端鏡像容錯,比如在連接斷開的時候進行重連(官方的Java和.net 客戶端提供了callback方法在監聽到鏈接失敗的時候調用。Java在Connection和channel類中提供了ShutdownListener 的callback方法,.net client在IConnecton中提供了ConnectionShuedown在Imodel中提供了ImodelShutdown事件供調用) 。也可以在client和server之間加入LoadBalancer.比如haproxy做負載均衡。 

指定mirror策略: 
有三種策略: 
all:隊列將mirrored到所有集群中的節點中,當新節點添加進來時也會mirrored到新的節點 
exactly(需指定count):如果節點數小於count數,則隊列將mirrored到所有的節點。如果節點數大於count,新的節點將不再創建隊列的mirror(即使原來已創建mirror的節點掛掉也不會創建) 
nodes:對指定的節點進行mirror。如果沒有一個指定的節點在運行中,那么只有client連接的那個節點才會聲明queue(這里有個遷移策略:假如queue是在[A,B]上且A為master,若給定的新的策略為nodes[C,D],那么為了防止數據丟失,在遷移中會同時存在[A,C,D]直到C,D已經同步好以后,A才會關閉) 
配置舉例: 
設置queue的名稱為ha.的為高可用: 
linux:rabbitmqctl set_policy ha-all "^ha\." '{"ha-mode":"all"}' 
win:rabbitmqctl set_policy ha-all "^ha\." "{""ha-mode"":""all""}" 
http api:PUT /api/policies/%2f/ha-all {"pattern":"^ha\.", "definition":{"ha-mode":"all"}} 
web ui: 
1:Navigate to Admin > Policies > Add / update a policy. 
2:Enter "ha-all" next to Name, "^ha\." next to Pattern, and "ha-mode" = "all" in the first line next to Policy. 
3:Click Add policy. 
舉例2: 
rabbitmqctl set_policy ha-two "^two\." \ 
   '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}' 

自動或手動同步: 
你可以查看哪些slave已經同步好了: 
rabbitmqctl list_queues name slave_pids synchronised_slave_pids 
你可以手動同步(默認手動同步): 
rabbitmqctl sync_queue name 
你可以取消自動同步: 
rabbitmqctl cancel_sync_queue name 
一個沒有同步的mirror,它仍然會同步后續插入隊列的數據,但是隊列前面的數據卻沒有。但是隨着隊列的不斷消費,導致空缺的部分的消息被消費掉了,此時mirror也可以是同步了的。 

3.主備集群 
主備方式(active,passive)只有一個節點處於服務狀態,可以結合pacemaker和ARBD, 
shovel簡單從一個broker的一個隊列中消費消息,且轉發該消息到另一個broker的交換機。 
這種方式用的比較少,這里就不做介紹了。詳見http://www.rabbitmq.com/pacemaker.html 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM