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 html

相關文章
相關標籤/搜索