1. 程式人生 > 實用技巧 >RabbitMQ(六)映象佇列

RabbitMQ(六)映象佇列

一、映象佇列 預設情況下,RabbitMQ叢集中的佇列只會儲存在某一個節點上,就是佇列宣告的那個節點上。當訪問叢集中的其他節點時,會把請求轉發給這個節點來進行處理。當這個節點故障時,叢集中的這個佇列就表現為不可用。佇列可以在多個節點中複製映象以保障可用性,稱之為映象佇列。 每一個映象佇列由一個master和若干個slave組成。佇列的master通常儲存在叢集的主節點上,沒個佇列有自己的主節點,映象佇列的所有操作都會首先在mastEr上執行然後廣播給其他映象。包括訊息入隊,推送給消費者、和消費確認等。 生產者傳送的訊息會在所有的映象中儲存一份副本,消費者不論連線哪個節點最終都會在master上操作,一旦master確認消費(ack)以後,映象佇列會丟棄這條訊息。因此映象佇列雖然增加了可用性(存在多個可用副本),但是多個節點間並沒有分攤負載,因為所有節點都會處理全量的訊息。 如果映象佇列的master宕機了,最老的映象將會晉升為新的master。未同步的映象也可以晉升為master,取決於佇列的映象引數。 二、如何配置映象佇列
映象引數通過policy來配置,一個policy通過正則表示式匹配一個或多個佇列。 命令列設定:e.g.: rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' 控制檯設定: 引數說明
ha-mode ha-params Result
exactly count Number of queue replicas (master plus mirrors) in the cluster. A count value of 1 means a single replica: just the queue master. If the node running the queue master becomes unavailable,
the behaviour depends on queue durability . A count value of 2 means 2 replicas: 1 queue master and 1 queue mirror. In other words: `NumberOfQueueMirrors = NumberOfNodes - 1`. If the node running the queue master becomes unavailable, the queue mirror will be automatically promoted to master according to the
mirror promotion strategy configured. If there are fewer than count nodes in the cluster, the queue is mirrored to all nodes. If there are more than count nodes in the cluster, and a node containing a mirror goes down, then a new mirror will be created on another node. Use of `exactly` mode with `"ha-promote-on-shutdown": "always"` can be dangerous since queues can migrate across a cluster and become unsynced as it is brought down.
all (none) Queue is mirrored across all nodes in the cluster. When a new node is added to the cluster, the queue will be mirrored to that node. This setting is very conservative. Mirroring to a quorum (N/2 + 1) of cluster nodes is recommended instead . Mirroring to all nodes will put additional strain on all cluster nodes, including network I/O, disk I/O and disk space usage.
nodes node names Queue is mirrored to the nodes listed in node names . Node names are the Erlang node names as they appear in rabbitmqctl cluster_status ; they usually have the form "[email protected]". If any of those node names are not a part of the cluster, this does not constitute an error. If none of the nodes in the list are online at the time when the queue is declared then the queue will be created on the node that the declaring client is connected to.
三、多少個映象是最優的 在所有的節點上設定映象是最保守的策略,可用性最高,但是會給叢集中的所有節點帶來額外的壓力,包括網路IO、磁碟IO和硬碟空間佔用。大多數場景下都沒有必要在每個節點上都儲存一份映象。 一般來說推薦設定過半節點的映象,例如3節點叢集設定2個映象,5節點叢集設定3個映象。 一些瞬變的資料或者時間敏感的資料,比如股票淨值資料,最好設定少量的映象甚至不要使用映象。 四、怎麼檢查佇列是否是映象狀態 映象佇列會在後臺管理頁面顯示策略名稱和額外的副本數量,例如下面這個佇列存在兩個副本,即一主一從 佇列詳情 如果僅有的一個映象節點宕機了 當添加了一個映象佇列的時候,會列印如下日誌 2018-03-01 07:26:33.121 [info] <0.1360.0> Mirrored queue 'two.replicas' in vhost '/': Adding mirror on node [email protected]: <37324.1148.0> 5.佇列master定位節點 rabbitmq中的每個佇列有一個primary副本,那個副本所在的節點稱之為佇列master。所有佇列的操作都要首選通過master執行然後傳播給其他映象,為了保證訊息的FIFO順序。 佇列master可以使用幾種不同的策略分佈在叢集的節點上, 三種宣告策略的方式如下:
  1. 使用x-queue-master-locator佇列宣告引數
  2. 設定queue-master-locator策略key
  3. 在配置檔案中定義queue_master_locator
可選擇的策略型別:
  • min-masters選擇承載了佇列master數量最少的節點
  • client-local選擇客戶端宣告佇列時連線上的那個節點
  • random隨機選擇一個節點
6.節點策略和遷移master 如果新的策略裡面沒有指定原來的master所在的節點,設定和修改佇列策略可能導致存在的佇列master下線。為了保證訊息不丟失,rabbitmq會保留現有的master直到至少有一個映象已經同步,即使同步需要很長時間。一旦同步成功,原master就會下線,隨著原來的佇列master下線,消費者將會從原來的master丟失連線並且重連。 例如:原來佇列在【A,B】節點,A是master,B是mirror。如果我們這個時候設定了新的policy定位在【C,D】節點,設定完成以後,佇列將會存在【A,C, D】節點上,等到C或D節點上的映象佇列同步完成,A上面的佇列將會下線。 7.排他佇列的映象 當宣告排他佇列的連線關閉的時候,排他佇列將會被刪除,所以對一個排他佇列做映象或者持久化是沒有意義的。因為一旦承載他的節點宕機了,宣告他的連線就會被關閉,隨之佇列將會被刪除。 所以排他佇列永遠不會配置映象副本或者持久化。 8.叢集中的非映象佇列 非映象佇列如果佇列的master可用的時候(佇列儲存的那個節點),客戶端可以連線任意一個節點對當前佇列進行操作,包括宣告、繫結、消費管理和訊息路由,對當前佇列的操作將會被叢集路由到對應master節點上進行執行。一旦master節點不可用, 如果佇列是持久化的佇列,佇列將會保持不可用狀態直到節點恢復。所有對佇列的操作將會失敗 如果佇列沒有持久化,佇列將會被刪除。 如果想要保證在任何時候佇列依然可用,可以把映象佇列配置為 promoted to master even when not in sync即使映象沒有同步也可以晉升為master 9.配置映象佇列的幾種方式 例如:想要宣告一個名稱為“ha-two”的策略,策略內容是匹配佇列名以“two.”開頭的佇列,在叢集中任意2個節點上保持映象,並且自動同步 9.1命令列方式 rabbitmqctl set_policy ha-two "^two\." \ '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}' 9.2傳送HTTP請求 PUT /api/policies/%2f/ha-two { "pattern":"^two\.", "definition": { "ha-mode":"exactly", "ha-params":2, "ha-sync-mode":"automatic" } } 9.3後臺管理頁面上宣告
  • Navigate to Admin > Policies > Add / update a policy.
  • Enter "ha-two" next to Name and "^two\." next to Pattern.
  • Enter "ha-mode" = "exactly" in the first line next to Policy, then "ha-params" = 2 in the second line, then "ha-sync-mode" = "automatic" in the third, and set the type on the second line to "Number".
  • Click Add policy.
10.映象佇列主從切換 當佇列master不可用 1.執行時間最長的映象將會晉升為master,因為這個映象最後可能從master全量同步。如果沒有映象完成了全量同步,那麼僅存在於master上的訊息將會丟失 2.之前連上映象節點的所有客戶端連線都會突然中斷。所有傳送給客戶端但是還沒有ACK的訊息將會重新入隊。這裡麵包括客戶端已經發出ACK但是在傳送給master過程中master宕機的,也包括從master廣播給映象佇列過程中丟失的訊息。無論是哪種情況,新晉升的master只能重新入隊還沒有ACK的訊息。 3.那些監聽了cancel事件的消費者將會被通知佇列下線 4.因為第二步過程中訊息的重新入隊,消費者有可能會重複消費到之前已經消費過的訊息 5.隨著選擇的映象晉升成為master以後,這時傳送給映象佇列的訊息就不會丟失了。訊息傳送給映象節點的操作將會路由到佇列master然後廣播給其他映象,如果master再宕機,一旦新的映象晉升為master以後,傳送給映象的訊息將會重新加入到佇列中,重複這個過程。 6.在訊息正在釋出並且客戶端已經接受到確認的時候,如果master或映象節點下線了,同步還沒有完成,客戶端傳送的訊息依然會被確認。從這點上來看,傳送給映象佇列和非映象佇列沒有區別 如果消費者使用自動簽收模式,訊息可能會丟失,這一點和非映象佇列沒有區別。因為broker認為自動簽收模式下,訊息只要傳送到消費者了就認為是確認傳送成功了。 映象佇列的master如果突然掛了,客戶端的連線突然中斷,如果消費者是自動簽收模式,這個時候正在傳送給客戶端的訊息可能永遠也不會被消費者接收到了 11.master節點故障消費感知 消費者正在消費映象佇列的訊息時,如果發生了故障轉移,主從切換,哪條訊息(傳送中的)被髮送到哪個消費者的記錄將會丟失,因此所有未確認的訊息被會被標記 redelivered並且重新發送。 如果消費者想要感知這一行為,可以設定 x-cancel-on-ha-failover引數為true,然後在故障轉移的時候,消費行為將會被取消,將會接收到cancel通知。 java程式碼示例 Channel channel = ...; Consumer consumer = ...; Map<String, Object> args = new HashMap<String, Object>(); args.put("x-cancel-on-ha-failover", true); channel.basicConsume("my-queue", false, args, consumer);