rocketmq (一)運行原理以及使用問題


使用消息中間件可以解決高並發,那是因為消息中間件可以將消息緩存到隊列之中。

但是 當消息 過多的時候,幾萬,幾十萬...消息中間件也可能會宕機,所以我們可以對消息中間件進行集群,在之前的activemq中

activemq支持jms規范,點對點 發布訂閱 消息模型,但是不支持分布式 (不支持集群) ,或者說集群比較麻煩 需要用到zk,activemq消息堆積能力沒rocetmq消息堆積能力強  每年的雙11 都是經過了驗證的

但是 rocetmq 就支持分布式,集群。它的消息隊列緩存的消息 比activemq更多

 

在消息中間件集群的時候,生產者可以通過輪詢的方式,將生產的消息依次發送到集群中不同的消息中間件,消費的時候,中間件 會均衡的將消息 發送給集群中不同的消費者

 什么是rocketmq:

  • 是一個隊列模型的消息中間件,具有高性能、高可靠、高實時、分布式特點。
  • Producer、Consumer、隊列都可以分布式。
  • Producer 向一些隊列輪流發送消息,隊列集合稱為 Topic,Consumer 如果做廣播消費,則一個 consumer 實例消費這個Topic 對應的所有隊列,如果做集群消費,則多個 Consumer 實例平均消費這個 topic 對應的隊列集合。
  • 能夠保證嚴格的消息順序
  • 提供豐富的消息拉取模式
  • 高效的訂閱者水平擴展能力
  • 實時的消息訂閱機制
  • 億級消息堆積能力
  • 較少依賴

rocketmq原理:

 說的rocketmq的時候需要說幾個名詞:

  Producer 消息生產者,負責產生消息,一般由業務系統負責產生消息。

  Consumer 消息消費者,負責消費消息,一般是后台系統負責異步消費。(分兩種消費者:一種是調用consumer的拉取方法從broker拉取消息,一種是Consumer 對象注冊一個 Listener 接口,一旦收到消息,Consumer 對象立刻回調 Listener 接口方法)

Producer Group 一類 Producer 的集合名稱,這類 Producer 通常發送一類消息,且發送邏輯一致

 Consumer Group 一類 Consumer 的集合名稱,這類 Consumer 通常消費一類消息,且消費邏輯一致。

  Broker 消息中轉角色,負責存儲消息,轉發消息,一般也稱為 Server。在 JMS 規范中稱為 Provider。

  Name Server 是一個幾乎無狀態節點,可集群部署,節點之間無任何信息同步(rocketmq尋址服務)

 

Name Server 是一個幾乎無狀態節點,可集群部署,節點之間無任何信息同步。 

Broker 部署相對復雜,Broker 分為 Master 與  Slave,一個 Master 可以對應多個 Slave,但是一個 Slave 只能 對應一個 Master,Master 與 Slave 的對應關系通過定相同的 BrokerName 不同的 BrokerId 來定義,BrokerId   為 0 表示 Master,非 0 表示 Slave。Master 也可以部署多個。每個 Broker 與  Name Server 集群中的所有節 點建立長連接,定時注冊 Topic 信息到所有 Name Server。 

Producer 與 Name Server 集群中的其中一個節點(隨機選擇)建立長連接,定期從 Name Server 取 Topic 路 由信息,並向提供 Topic 服務的 Master 建立長連接,且定時向 Master 發送心跳。Producer 完全無狀態,可 集群部署。

Consumer 與 Name Server 集群中的其中一個節點(隨機選擇)建立長連接,定期從 Name Server 取 Topic 路 由信息,並向 提供 Topic 服務的 Master、Slave 建立長連接,且定時向 Master、Slave 發送心跳。Consumer 既可以從 Master 訂閱消息,也可以從 Slave 訂閱消息,訂閱規則由 Broker 配置決定。

 

集群消費:

一個 Consumer Group 中的 Consumer 實例平均分攤消費消息。例如某個 Topic 有 9 條消息,其中一個 Consumer Group 有 3 個實例(可能是 3 個進程,或者 3 台機器),那么每個實例只消費其中的 3 條消息

順序消息:

消費消息的順序要同發送消息的順序一致,在 RocketMQ 中,主要的是局部順序,即一類消息為滿足順 序性,必須 Producer 單線程順序發送,且發送到同一個隊列,這樣 Consumer 就可以按照 Producer 收送 的順序去消費消息。

普通順序消息:

順序消息的一種,正常情況下可以保證完全的順序消息,但是一旦發生通信異常,Broker 重啟,由於隊列 總數發生發化,哈希取模后定位的隊列會發化,產生短暫的消息順序不一致。 如果業務能容忍在集群異常情況(如某個 Broker 宕機或者重啟)下,消息短暫的亂序,使用普通順序方式比較合適。

嚴格順序消:

順序消息的一種,無論正常異常情況都能保證順序,但是犧牲了分布式 Failover 特性,即 Broker 集群中只 要有一台機器不可用,則整個集群都不可用,服務可用性大大降低。 如果服務器部署為同步雙寫模式,此缺陷可通過備機自動切換為主避免,不過仍然會存在幾分鍾的服務不 可用。(依賴同步雙寫,主備自動切換,自動切換功能目前還未實現) 目前已知的應用只有數據庫 binlog 同步強依賴嚴格順序消息,其他應用絕大部分都可以容忍短暫亂序,推 薦使用普通的順序消息

使用消息中間件需要解決哪些問題:

1.消息的優先級問題:

   規范中描述的優先級是在一個消息隊列中,每條消息都有不同的優先級,一般用整數來描述,優先級高的消息先投遞,如果消息完全在一個內存隊列中,那么在投遞前可以按照優先級排序,令優先級高的先投遞。 由於RocketMQ 所有消息都是持久化的,所以如果按照優先級來排序,開銷會非常大,因此 RocketMQ 沒有特 意支持消息優先級,但是可以通過變通的方式實現類似功能,即單獨配置一個優先級高的隊列,和一個普通優先級 的隊列, 將不同優先級發送到不同隊列即可。 對於優先級問題,可以歸納為 2 類

1.只要達到優先級目的即可,不是嚴格意義上的優先級,通常將優先級划分為高、中、低,或者再多幾個級 別。每個優先級可以用不同的 topic 表示,發消息時,定不同的 topic 來表示優先級,這種方式可以解決 絕大部分的優先級問題,但是對業務的優先級精確性做了妥協。

2 .嚴格的優先級,優先級用整數表示,例如 0 ~ 65535,這種優先級問題一般使用不同 topic 解決就非常不合適 。如果要讓 MQ 解決此問題,會對 MQ 的性能造成非常大的影響。這里要確保一點,業務上是否確實需 要這種嚴格的優先級,如果將優先級壓縮成幾個,對業務的影響有多大?

2.消息有序性:
  消息有序的是一類消息消費時,能按照發送的順序來消費。例如:一個訂單產生了 3 條消息,分別是訂單創 建,訂單付款,訂單完成。消費時,要按照這個順序消費才能有意義。但是同時訂單之間是可以並行消費的。 RocketMQ 可以嚴格的保證消息有序。

3.消息過濾

Broker 端消息過濾 在 Broker 中,按照 Consumer 的要求做過濾,優點是減少了對於 Consumer 無用消息的網絡傳輸。 缺點是增加了 Broker 的負擔,實現相對復雜

Consumer 端消息過濾 這種過濾方式可由應用完全自定丿實現,但是缺點是很多無用的消息要傳輸到 Consumer 端。

4.消息持久化

 消息中間件通常采用的幾種持久化方式:

(1). 持久化到數據庫,例如 Mysql。

(2). 持久化到 KV 存儲,例如 levelDB、伯克利 DB 等 KV 存儲系統。

(3). 文件記彔形式持久化,例如 Kafka,RocketMQ 

(4). 對內存數據做一個持久化鏡像,例如 beanstalkd,VisiNotify (1)、(2)、(3)三種持久化方式都具有將內存隊列 Buffer 進行擴展的能力,(4)只是一個內存的鏡像,作用是當 Broker 掛掉重啟后仍然能將之前內存的數據恢復出來。 JMS 和 CORBA Notification 規范沒有明確說明如何持久化,但是持久化部分的性能直接決定了整個消息中間件 的性能。 RocketMQ 參考了 Kafka 的持久化方式,充分利用 Linux 文件系統內存 cache 來提高性能。

5.影響消息可靠性的因素:

影響消息可靠性的幾種情況: (1). Broker 正常關閉

(2). Broker 異常 崩潰

(3). OS 崩潰

(4). 機器掉電,但是能立即恢復供電情況。

(5). 機器無法開機(可能是 cpu、主板、內存等關鍵設備損壞)

(6). 磁盤設備損壞。

(1)、(2)、(3)、(4)四種情況都屬於硬件資源可立即恢復情況,RocketMQ 在這四種情況下能保證消息不丟,或 者丟失少量數據。 (5)、(6)屬於單點故障,且無法恢復,一旦發生,在此單點上的消息全部丟失。RocketMQ 在這兩種情況下,通 過異步復制,可保證 99%的消息不丟,但是仍然會有極少量的消息可能丟失。通過同步雙寫技術可以完全避免單點, 同步雙寫勢必會影響性能,適合對消息可靠性要求極高的場合,例如和賬本 相關的應用。 RocketMQ 從 3.0 版本開始支持同步雙寫。

6.消息延遲

在消息不堆積的情況下,消息到大Broker后。能like到大consumer   rocketmq 使用長輪詢pull (拉 )方式,可以保證消息非常實時,消息實時性不低於push(推)

7.關於消息的消費和這回:

每個消息必須投遞一次 RocketMQ Consumer 先pull 消息到本地,消費完成后,才向服務器這回回 ack,如果沒有消費一定不會 ack 消息

(1). 發送消息階段,不允許發送重復的消息。

(2). 消費消息階段,不允許消費重復的消息。 只有以上兩個條件都滿足情況下,才能認為消息是“Exactly Only Once”,而要實現以上兩點,在分布式系統環 境下,不可避免要產生巨大的開銷。所以 RocketMQ 為了追求高性能,並不保證此特性,要求在業務上迕行去重, 也就是說消費消息要做到冪等性。RocketMQ 雖然不能嚴格保證不重復,但是正常情況下很少會出現重復發送、消費情況,只有網絡異常,Consumer 啟停等異常情況下會出現消息重復。 此問題的本質原因是網絡調用存在不確定性,即既不成功也不失敗的第三種狀態,所以才產生了消息重復性問 題。

8.rocketmq 中Broker消息隊列緩存滿了:

Broker 的 Buffer 通常的是 Broker 中一個隊列的內存 Buffer 大小,這類 Buffer 通常大小有限,如果 Buffer 滿 了以后怎舉辦? 下面是 CORBA Notification 規范中處理方式:

(1).  拒絕新來的消息,向 Producer 這回 RejectNewEvents 錯誤碼。

(2). 按照特定策略丟棄已有消息

RocketMQ 沒有內存 Buffer 概念,RocketMQ 的隊列都是持久化磁盤,數據定期清除。 對於此問題的解決思路,RocketMQ 同其他 MQ 有非常顯著的區別,RocketMQ 的內存 Buffer 抽象成一個無限 長度的隊列,不管有多少數據進來都能裝得下,這個無限是有前提的,Broker 會定期刪除過期的數據,例如 Broker 只保存 3 天的消息,那么這個 Buffer 雖然長度無限,但是 3 天前的數據會被從隊尾刪除。

9. 回溯消費

回溯消費是指 Consumer 已經消費成功的消息,由於業務上需求需要重新消費,要支持此功能,Broker 在向 Consumer 投遞成功消息后,消息仍然需要保留。並且重新消費一般是按照時間維度,例如由於 Consumer 系統故障, 恢復后需要重新消費 1 小時前的數據,那么Broker 要提供一種機制,可以按照時間維度來回退消費進度。 RocketMQ 支持按照時間回溯消費,時間維度精確到毫秒,可以向前回溯,也可以向后回溯。

 

10.消息堆積:

消息中間件的主要功能是異步解耦,迓有個重要功能是擋住前端的數據洪峰,保證后端系統的穩定性,這就要 求消息中間件具有一定的消息堆積能力,消息堆積分以下兩種情況:

(1). 消息堆積在內存 Buffer,一旦超過內存 Buffer,可以根據一定的丟棄策略來丟棄消息,如 CORBA Notification 規范中描述。適合能容忍丟棄消息的業務,這種情況消息的堆積能力主要在於內存 Buffer 大小,而且消息 堆積后,性能下降不會太大,因為內存中數據多少對於對外提供的訪問能力影響有限。

(2). 消息堆積到持久化存儲系統中,例如 DB,KV 存儲,文件記彔形式。 當消息不能在內存 Cache 命中時,要不可避免的訪問磁盤,會產生大量讀 IO,讀 IO 的吞吐量直接決定了 消息堆積后的訪問能力。 評估消息堆積能力主要有以下四點:

(1). 消息能堆積多少條,多少字節?即消息的堆積容量。

(2). 消息堆積后,收消息的吞吐量大小,是否會受堆積影響?

(3). 消息堆積后,正常消費的 Consumer 是否會受影響?

(4). 消息堆積后,訪問堆積在磁盤的消息時,吞吐量有多大?

11分布式事務

已知的幾個分布式事務規范,如 XA,JTA 等。其中 XA 規范被各大數據庫廠商廣泛支持,如 Oracle,Mysql 等。 其中 XA 的 TM 實現佼佼者如 Oracle Tuxedo,在金融、電信等領域被廣泛應用。 分布式事務涉及到兩階段提交問題,在數據存儲方面的方面必然需要 KV 存儲的支持,因為第二階段的提交回 滾需要修改消息狀態,一定涉及到根據 Key 去查找 Message 的動作。RocketMQ 在第二階段繞過了根據 Key 去查找 Message 的問題,采用第一階段發送 Prepared 消息時,拿到了消息的 Offset,第二階段通過 Offset 去訪問消息,並修改狀態,Offset 就是數據的地址。 RocketMQ 這種實現事務方式,沒有通過 KV 存儲做,而是通過 Offset 方式,存在一個顯著缺陷,即通過 Offset 更改數據,會令系統的臟頁過多,需要特別關注。

12. 定時消息

定時消息是指消息發到 Broker 后,不能立刻被 Consumer 消費,要到特定的時間點或者等待特定的時間后才能 被消費。 如果要支持任意的時間精度,在 Broker 層面,必須要做消息排序,如果再涉及到持久化,那么消息排序要不可避免的產生巨大性能開銷。 RocketMQ 支持定時消息,但是不支持任意時間精度,支持特定的 level,例如定時 5s,10s,1m 等。 4.15 消息重試 Consumer 消費消息失敗后,要提供一種重試機制,令消息再消費一次。Consumer 消費消息失敗通常可以分為 有以下幾種情況

1. 由於消息本身的原因,例如反序列化失敗,消息數據本身無法處理(例如話費充值,當前消息的手機號被注銷,無法充值)等。 這種錯諢通常需要跳過這條消息,再消費其他消息,而這條失敗的消息即使立刻重試消費,99%也不成功, 所以最好提供一種定時重試機制,即過 10s 秒后再重試。

2. 由於依賴的下游應用服務不可用,例如 db 連接不可用,外系統網絡不可達等。 遇到這種錯誤,即使跳過當前失敗的消息,消費其他消息同樣也會報錯。這種情況建議應用 sleep 30s,再 消費下一條消息,這樣可以減輕 Broker 重試消息的壓力。

13.消息重試

Consumer 消費消息失敗后,要提供一種重試機制,令消息再消費一次。Consumer 消費消息失敗通常可以分為 有以下幾種情冴 1. 由於消息本身的原因,例如反序列化失敗,消息數據本身無法處理(例如話費充值,當前消息的手機號被 注銷,無法充值)等。 這種錯誤通常需要跳過這條消息,再消費其他消息,而這條失敗的消息即使立刻重試消費,99%也不成功, 所以最好提供一種定時重試機制,即過 10s 秒后再重試。 2. 由於依賴的下游應用服務不可用,例如 db 連接不可用,外系統網絡不可達等。 遇到這種錯誤,即使跳過當前失敗的消息,消費其他消息同樣也會報錯。這種情況建議應用 sleep 30s,再 消費下一條消息,這樣可以減輕 Broker 重試消息的壓力。

文章借鑒:

RocketMQ 開發指南

 


免責聲明!

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



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