日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Highly Available (Mirrored) Queues

發布時間:2024/4/11 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Highly Available (Mirrored) Queues 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。


本文翻譯RabbitMQ官方文檔:Highly Available (Mirrored) Queues,原文地址:http://www.rabbitmq.com/ha.html。(翻譯水平有限,不喜輕噴~~)

高可用(鏡像)隊列

默認情況下,queues存放在RabbitMQ集群的單個節點之上。exchanges和bindings恰恰相反,在集群中的所有節點中都有存檔。queues可以配置鏡像以此可以在多個節點中有備份。每個鏡像隊列包含一個master節點和一個或者多個slave節點。如果master節點由于某種原因失效,那么“資歷最老”的slave節點將被提升為新的master節點。(譯者注:根據進入的時間排序,時間最長的節點即為資歷最老的節點。)

發送的消息將被復制到隊列的所有鏡像節點。Consumer連接的是master節點,而不是其他的slave節點(譯者注:就算程序連接的是slave節點,也會路由到master節點,然后建立tcp連接),被消費并被確認的消息將會被清除。鏡像隊列增強了其可用性,但是并沒有分攤負載。

這里并不推薦在局域網之外搭建RabbitMQ集群,這樣會有網絡分區的風險。同時,客戶端程序最好也部署在相同的局域網之內。

How Mirroring is Configured

在我們演示怎么配置鏡像隊列之前先看下之前是怎么使用的,然后我們再來陳述現在推薦怎么使用。

除了mandatory這個屬性(亦或者durable,exclusive)之外,RabbitMQ中的queue也有可選的參數(parameters, 也可以稱之為arguments), 有時會涉及到類似x-arguments這個參數。x-arguments可以用來配置鏡像參數,但是現在又更好的辦法,那就是通過policies(策略)。

Queue Arguments that Control Mirroring

Policies可以在任何適合改變,比如期初你創建了一個無鏡像的queue,在之后的某個節點你可以為這個queue配置鏡像,反之亦然。對于沒有配置鏡像的queue(non-mirrored)和配置了鏡像但是又沒有slave鏡像節點的queue之間是有區別的,前者卻反了額外的鏡像機制,但是可以有更高的吞吐量。

通過policy創建對象,這里包括了兩個關鍵的參數:ha-mode和ha-params(可選)。下表做了相應的解釋

ha-modeha-paramsResult
all(absent)在集群中的每個節點都有鏡像。當一個節點添加到集群中時,這個節點同樣會有相應的鏡像
exactlycount指定在集群中鏡像的個數。如果集群中節點的個數小于count的值,那么所有的節點都會配置鏡像。如果其中一個鏡像掛掉,那么會在另一個節點生成新的鏡像。ha-mode:exactly和ha-promote-on-shutdown:always一起使用將會很危險。
nodesnode names在指定的節點列表中配置鏡像。節點名稱可以通過rabbitmqctl cluster_status命令獲取,通常名稱是“rabbit@hostname”的這種形式。如果這些指定的節點都處于不可用狀態(宕機或者關閉服務等),那么客戶端程序會在自己所連接的那么節點上創建queue。

(譯者注:當所有slave都出在(與master)未同步狀態時,并且ha-promote-on-shutdown設置為when-synced(默認)時,如果master因為主動的原因停掉,比如是通過rabbitmqctl stop命令停止或者優雅關閉OS,那么slave不會接管master,也就是此時鏡像隊列不可用;但是如果master因為被動原因停掉,比如VM或者OS crash了,那么slave會接管master。這個配置項隱含的價值取向是保證消息可靠不丟失,放棄可用性。如果ha-promote-on-shutdown設置為always,那么不論master因為何種原因停止,slave都會接管master,優先保證可用性。

試想一下,如果ha-mode設置為exactly,ha-params設置為2,當其中一個鏡像節點掛掉,那么在集群中的另一個節點將會被設置為鏡像,此鏡像尚未與master同步,此時master節點也掛掉,那么這個鏡像將被提升為master,造成數據丟失。)

To How Many Nodes to Mirror?

ha-mode:all是一種非常保守且不必要選擇。在有三個或者更多節點的集群中推薦配置大多數個數即可. 比如3個幾點的集群配置為2, 或者5個節點的集群配置為3。有些數據是瞬時性的,對延遲要求比較高,可以配置更少的鏡像個數,甚至可以不配置鏡像。

Queue Masters, Master Migration, Data Locality

Queue Master Location

每個queue都有一個master節點,所有對于queue的操作都是事先在master上完成,之后再slave上進行相同的操作。保證消息的FIFO順序是非常必要的。

每個不同的queue可以坐落在不同的集群節點上,這些queue如果配置了鏡像隊列,那么會有1個master和多個slave。基本上所有的操作都落在master上,那么如果這些queues的master都落在個別的服務節點上,那么勢必會影響性能,而其他的節點又很空閑,這樣就無法做到負載均衡。

關于master的分配有幾種策略。你可以在queue聲明的時候使用x-queue-master-locator參數,或者在policy上設置queue-master-locator,或者直接在rabbitmq的配置文件中定義queue_master_locator。這里有三種可供選擇的策略:

  • min-masters:選擇master數最少的那個服務節點
  • client-local:選擇與client相連接的那個服務節點
  • random:隨機分配

“nodes" Policy and Migrating Masters

當policy的ha-mode設置為nodes時,可以在指定列表中配置鏡像隊列,如果新配置或者修改的nodes列表中沒有當前的master,那么勢必會造成數據的丟失。然而RabbitMQ會保持現有的master直到其他的鏡像至少有一個節點已經完全同步。但是如果發生同步的操作,隊列會出現假死的現象:consumer需要和master重新建立連接。

(譯者注:當調用同步命令后,隊列開始阻塞,無法對其進行操作,直到同步完畢。當ha-sync-mode=automatic時,新加入節點時會默認同步已知的鏡像隊列。由于同步過程的限制,所以不建議在生產的active隊列(有生產消費消息)中操作。)

舉例,queue在節點[A, B]中,并且A為master,此時設置節點的策略為在[C,D]中,那么首先queue會存在在[A,C,D]中,等到完全同步之后,A會被shutdown,進而在[C,D]中選擇一個master。

Exclusive Queues

當一個connection關閉的時候,其上鎖declare的排他(exclusive)queues將會被刪除。對于一個排他隊列來說,為它設置鏡像隊列是沒有用的。

排他隊列是不能被鏡像的,也不能被持久化。

Examples

下面的例子是為所有以"ha."開頭的隊列設置名為“ha-all"的policy。

modedescription
rabbitmqctlrabbitmqctl set_policy ha-all “^ha.” ‘{“ha-mode”:“all”}’
rabbitmqctl(Windows)rabbitmqctl set_policy ha-all “^ha.” “{”“ha-mode”":"“all”"}"
HTTP APIPUT /api/policies/%2f/ha-all {“pattern”:"^ha.", “definition”:{“ha-mode”:“all”}}
Web UINavigate to Admin > Policies> Add/ update a policy. Enter “ha-all” next to Name, “^ha.” next to Pattern, and “ha-mode”=“all” in the first line next to Policy. Click Add policy.

為每個以“two.”開頭的隊列設置兩個節點的鏡像,并且設置為自動同步模式:

modedescription
rabbitmqctlrabbitmqctl set_policy ha-two “^two.” ‘{“ha-mode”:“exactly”, “ha-params”:2, “ha-sync-mode”:“automatic”}’
rabbitmqctl (Windows)rabbitmqctl set_policy ha-two “^two.” “{”“ha-mode”":"“all”","“ha-params”":2, ““ha-sync-mode””:"“automatic”"}"
HTTP APIPUT /api/policies/%2f/ha-two {“pattern”:"^two.",“definition”:{“ha-mode”:“exactly”,“ha-params”:2,“ha-sync-mode”:“automatic”}}
Web UINavigate 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 the type on the second line to “Number”. Click Add policy.

為每個以“node."開頭的隊列分配指定的節點做鏡像

modedescription
rabbitmqctlrabbitmqctl set_policy ha-nodes “^nodes.” ‘{“ha-mode”:“nodes”,“ha-params”:[“rabbit@nodeA”,“rabbit@nodeB”]}’
rabbitmqctl (Windows)rabbitmqctl set_policy ha-nodes “^nodes.” “{”“ha-mode”":"“node”","“ha-params”":["“rabbit@nodeA”","“rabbit@nodeB”"]}"
HTTP APIPUT /api/policies/%2f/ha-nodes {“pattern”:"^node.",“definition”:{“ha-mode”:“nodes”,“ha-params”:[“rabbit@nodeA”,“rabbit@nodeB”]}}
Web UINavigate to Admin > Policies > Add / update a policy. Enter “ha-nodes” next to Name and “^nodes.” next to Pattern. Enter “ha-mode” = “nodes” in the first line next to Policy, then “ha-params” in the second line, set the second line’s type to “List”, and then enter “rabbit@nodeA” and “rabbit@nodeB” in the sublist which appears. Click Add policy.

Mirrored Queue Implementation and Semantics

正如先前所論述的,每個鏡像隊列中擁有一個master和多個slave,這些都分布在不同的節點上。在master上的操作會在slave上一樣的執行,這樣才能保持一致的狀態。對于鏡像隊列,客戶端Basic.Publish操作會同步到所有節點(消息同時發送到master和所有slave上,如果此時master宕掉了,消息還發送slave上,這樣當slave提升為master的時候消息也不會丟失),而其他操作則是通過master中轉,再由master將操作作用于slave。比如一個Basic.Get操作,假如客戶端與slave建立了TCP連接,首先是slave將Basic.Get請求發送至master,由master備好數據,返回至slave,投遞給消費者。

All actions other than publishes go only to the master, and the master then broadcasts the effect of the actions to the mirrors.

如果某個slave失效了,系統處理做些記錄外幾乎啥都不做:master依舊是master,客戶端不需要采取任何行動或者被通知slave已失效。注意slave的失效不會被立刻檢測出來,

如果master失效了,那么slave中的一個必須被選中為master。此時會發生如下的情形:

  • 被選中作為新的master的slave通常是最老的那個,因為最老的slave與前任master之間的同步狀態應該是最好的。然而,需要注意的是,如果存在沒有任何一個slave與master完全同步的情況,那么前任master中未被同步的消息將會丟失。
  • slave節點認為目前所有的消費者都已經突然的disconnect了。它會requeue所有被發送到客戶端但沒有被ack的消息。這里包括客戶端以及發送ack但是丟失在返回broker的路上,或者master已經收到但是其他的slave沒有收到,這些消息都會被requeue。無論何種清理,新的master只能requeue所有沒有被ack的消息。
  • 消費端如果引入了Consumer Cancellation Notification,那么當當前的queue掛掉的時候應該被通知到。
  • 由于requeue的存在,客戶端當重新消費queue的時候,有可能將之前消費過的消息又順序的消費一遍。
  • 當一個slave提升為master的時候,發送到當前鏡像隊列的消息將不會丟失(除非這個新的master緊接著掛了)。消息發送到一個slave的時候,將會被路由到master上,進而又被復制到所有的slave上。此時如果master掛了,消息將會繼續發送到slave上,當一個slave提升為master的時候,這些消息會被存入queue中。
  • 客戶端如果在發送消息是采用了publisher confirm機制,那么在消息發送和消息確認之間master掛掉(或者任何slave掛掉)都不會影響confirm機制的正確運行。
  • 如果你在消費一個鏡像隊列的時候這是autoAck=true(客戶端不會進行消息確認),那么消息有可能會丟失。broker中的消息一旦發送出去就會被立刻確認(被確認的消息不能再被消費,且broker內部線程會執行清理工作將此消息清除),如果與客戶端建立的連接突然中斷,那么消息將會永遠丟失。所以為了確保消息不丟失,還是建議你在消費時將autoAck設置為false。

    Publisher Confirms and Transactions

    RabbitMQ的鏡像隊列同時支持publisher confirm和事務兩種機制。在事務機制中,只有當前事務在全部鏡像queue中執行之后,客戶端才會收到Tx.CommitOk的消息。同樣的,在publisher confirm機制中,向publisher進行當前message確認的前提是該message被全部鏡像所接受了。

    Flow Control

    基于credit的算法來實現限制消息發送的速率。

    Master Failures and Consumer Cancellation

    若客戶端在消費的時候執行了參數x-cancel-on-ha-failover=true,那么當在故障處理的時候將會停止消費,并且會受到一個"consumer cancellation notification". 這樣消費需要重新發送Basic.Consume進而可以重新消費。

    舉例:

    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);

    Unsynchronised Mirrors

    一個節點可以在任何時候加入集群之中。根據queue的配置,當新節點加入進來的時候,這個queue有可能在這個新的節點上添加一個鏡像,此時這個鏡像(slave)是空的,它不包含任何queue中已經存在的內容。新加入的鏡像可以收到生產者新發送過來的消息,其內容與其他鏡像的尾部保持一致。隨著queue中的消息被逐漸的消費,新加入的鏡像中“錯失”的消息逐漸減少,直到與其他鏡像保持一致,既而就已經完全處于同步狀態。但是需要注意的是,上述的同步行為是基于客戶端的操作而觸發的。

    所以新加入的鏡像并沒有提供額外的冗余和可靠性保障,除非它能精確的同步。將新節點加入已存在的鏡像隊列是,默認情況下ha-sync-mode=manual,鏡像隊列中的消息不會主動同步到新節點,除非顯式調用同步命令。當調用同步命令后,隊列開始阻塞,無法對其進行操作,直到同步完畢。當ha-sync-mode=automatic時,新加入節點時會默認同步已知的鏡像隊列。由于同步過程的限制,所以不建議在生產的active隊列(有生產消費消息)中操作。

    可以使用下面的命令來查看那些slaves已經完成同步:

    rabbitmqctl list_queues name slave_pids synchronised_slave_pids

    可以通過手動的方式同步一個queue:

    rabbitmqctl sync_queue name

    同樣也可以取消某個queue的同步功能:

    rabbitmqctl cancel_sync_queue name

    當然這些都可以通過management插件來設置。

    Stopping nodes and synchronisation

    如果你關閉了鏡像隊列中的master節點,那么剩余的鏡像中會選舉一個作為新的master節點(假設都處于同步的狀態)。如果你繼續關閉節點直到沒有多余鏡像了,那么此時只有一個節點可用,這個節點也是master節點。如果這個鏡像隊列配置了持久化屬性(durable=true)。那么當最后的節點重啟之后,消息不會丟失。然后你再重啟其他的節點,它們會陸續的加入到鏡像隊列中來。

    然而,目前還沒有方法判斷一個重新加入的鏡像是否保持和master同步的狀態,因此每當一個節點加入或者重新加入(例如從網絡分區中恢復過來)鏡像隊列,之前保存的隊列內容會被清空。

    Stopping Master Nodes with Only Unsynchronised Mirrors

    當所有slave都出在(與master)未同步狀態時,并且ha-promote-on-shutdown設置為when-synced(默認)時,如果master因為主動的原因停掉,比如是通過rabbitmqctl stop命令停止或者優雅關閉OS,那么slave不會接管master,也就是此時鏡像隊列不可用;但是如果master因為被動原因停掉,比如VM或者OS crash了,那么slave會接管master。這個配置項隱含的價值取向是保證消息可靠不丟失,放棄可用性。如果ha-promote-on-shutdown設置為always,那么不論master因為何種原因停止,slave都會接管master,優先保證可用性。

    Loss of Master While All Mirrors are Stopped

    (略。實際上是不知道這段要表達什么gui。)

    Batch Synchronization

    RabbitMQ 3.6.0引入了一個與鏡像隊列有關的參數:ha-sync-batch-size。可以批量的進行消息同步,進而非常可觀的提升同步處理的效率。之前的版本默認只能同步一條消息。
    關于ha-sync-batch-size的取值,你需要考慮一下幾個方面:

    • 消息的平均大小
    • RabbitMQ節點間的網絡吞吐量
    • net_ticktime的值(參考:http://www.rabbitmq.com/nettick.html)

    舉個例子,如果你需要每次同步50000條消息,每條消息平均大小為1KB,那么ha-sync-batch-size設置為約49MB左右。你需要確tim保你的網絡在鏡像節點之間能夠支持這樣的吞吐。如果你批量發送一批消息所使用的時間大于net_ticktime,那么集群有可能認為發生了網絡分區。

    Configuring Synchronisation

    如果一個queue正在同步,所有對于其他的queues的操作將會被阻塞。一個queue有可能因為同步而被阻塞幾分鐘,幾小時甚至幾天。

    將新節點加入已存在的鏡像隊列是,默認情況下ha-sync-mode=manual,鏡像隊列中的消息不會主動同步到新節點,除非顯式調用同步命令。當調用同步命令后,隊列開始阻塞,無法對其進行操作,直到同步完畢。當ha-sync-mode=automatic時,新加入節點時會默認同步已知的鏡像隊列。由于同步過程的限制,所以不建議在生產的active隊列(有生產消費消息)中操作。


    歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。


    總結

    以上是生活随笔為你收集整理的Highly Available (Mirrored) Queues的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。