天天看點

RocketMQ介紹

一、什麼是RocketMQ

RocketMQ 是一個分布式消息中間件,其具有低延遲、高性能和可靠性、萬億級容量、靈活的可擴充性特性。它主要有四部分組成,分别為 name servers,brokers,producers and consumers。

每部分都可以進行水準擴充,而不會出現單點問題。

  • NameServer Cluster:名稱服務叢集,提供輕量級的服務發現與路由服務,每個名稱伺服器記錄了全部的 broker 的路由資訊,并且提供相應的讀寫服務,支援快速存儲擴充。
  • Broker Cluster:broker 叢集,broker 通過提供輕量級的主題和隊列機制來維護消息存儲。它支援推和拉兩種模型,包含容錯機制(2 個副本或 3 個副本),并提供了強大的平滑峰值,提供積累數以億計的消息并保證其在原始時間順序的被消費能力。

此外,broker 也提供災難恢複、豐富的度量統計和警報機制,所有這些能力在傳統的消息傳遞系統裡面都是沒有的。

  • Producer Cluster:生産者叢集,提供分布式部署,分布式的生産者發送消息到 broker 叢集,具體選擇哪一個 broker 機器是通過一定的負載均衡政策來決定的,發送消息中支援故障快速恢複,并且具有較低的延遲時間
  • Consumer Cluster:消費者叢集,消費者在推和拉模型中支援分布式部署。它還支援叢集消費和消息廣播。它提供了實時消息訂閱機制,可以滿足大多數消費者的需求。

broker 在啟動時候會去連結 NameServer,然後注冊 topic 資訊到 NameServer,NameServer 維護了所有 topic 的資訊和對應的 broker 路由資訊,broker 與 NameServer 之間是有心跳檢查的,NameServer 發現 broker 挂了後,會從注冊資訊裡面删除該 broker,這類似 zookeeper 實作的服務注冊;producer 則需要配置 nameserver 的位址,然後定時從 NameServer 擷取對應 topic 的路由資訊(這個 topic 的消息應該路由到那個 broker)。

同時 producer 與 NameServer,proudcer 與 broker 有心跳檢查;同理 Consumer 需要配置 NameServer 的位址,然後定時從 NameServer 擷取對應 topic 的路由資訊(應該從那個 broker 的消息隊列擷取消息),同時 Consumer 與 NameServer,Consumer 與 broker 有心跳檢查。

二、RocketMQ概念

1. MQ

Message Queue消息隊列,既然是隊列,就要實作資料結構中隊列的基本特征,比如先進先出,入隊、出隊操作等。

RocketMQ就是把記憶體中使用的那個隊列,變成一個獨立的、大家都可以用的隊列系統。

2. Topic

一個業務事件,是整個MQ領域最核心的概念,無論是生産還是消費都是針對Topic進行操作。

如果MQ是個大的隊列,隻有一個隊列可以用太浪費了吧,來分一分,分解成很多個小的獨立的隊列。RocketMQ變成一個管理隊列的系統,而分解下來的若幹個小的隊列通過什麼來區分呢?

就是通過topic。

比如我的業務定義topic:tp_im_event。你的業務定義topic:tp_cargo_event,那就是兩個小隊列了,我的業務用我的隊列,你的項目用你的隊列。Topic就是隊列的名字。

3. Queue

既然Topic是隊列的名字,那麼queue就表示真實操作的隊列了。一開始的時候一個Topic就對應一個queue,多好,一個是名字、一個是現實。可是用着用着就悲催了,為啥?消息操作太多了,全都放在一個小隊列上。為了提高效率,咋整??RocketMQ是這樣做的,一個Topic綁定的是一組queue,這樣每個queue分攤部分壓力,性能就上去了。

讀隊列個數:可以用來讀取資料的隊列個數

寫隊列個數:可以用來寫入資料的隊列個數

queue:真實存儲資料用的隊列。

4. Message

隊列存儲的是消息!Message!盡量小,别發個檔案啊什麼的大東西,後面真心扛不住(超過特定大小還會報錯)。

5. Tag

一個queue裡都是消息,如何對這些消息進行歸類呢?為了進一步細化消息,有了Tag的概念。可以通過Tag對相同消息進行歸類,這樣使用者就可以隻訂閱一部分的消息了(隻訂閱部分Tag)

比如:有一個Topic叫做‘發貨’,下遊消費者希望可以根據貨源進行不同的處理,可以通過‘tag=北京’以及‘tag=上海’來區分不同的發貨源。下遊消費者,可以單獨訂閱‘上海’的貨物,或者‘tag=上海|江蘇|浙江’來訂閱這三個地區的貨物,還可以‘tag=*’來訂閱全國的貨物。

6. Key

發送了某個消息,但是希望在背景很友善的搜尋到,就要通過key了。可以根據key搜尋到所有相關的Message。可以認為RocketMQ内部維護了一個非常大的HashMap,key就是這個key,value就是Message,如果出現Hash沖突就用連結清單來報錯對應關系。

7. Producer

生産者:針對某一個Topic制造資料,把資料塞到queue裡。(發消息的)

8. Producer Group

管理消息的時候,我們肯定會遇見這個問題,某個消息誰發的?RocketMQ把發送者的身份抽象成了Producer Group,就是[發送組]。

簡單點:這個東西命名成項目名就行,相同Producer Group保持相同業務行為。

9. Consumer

消費者:把queue裡面的消息拿出來用

消費行為:如何處理通過Topic+Tag定位的消息。

10. Consumer Group

一個RocketMQ叢集是如何區分消費者是誰的呢?就是通過消費組,相同消費組的機器,MQ認為消費行為是一緻的。業務上一定要保證相同消費組有相同的消費行為。對于不同的消費組名字,RocketMQ就認為是個不同消費者了。如果修改了消費組的名字,那就是新的消費者,就會按照新的消費組的消費進度處理消費。

消息那麼多,項目都重新開機無數次了,RocketMQ是如何記錄消息消費到什麼地方了呢?

也是通過消費組,RocketMQ内部會維護一個關系,記錄Consumer Group和消費進度之間的聯系。是以,如果把Consumer Group的名字改掉是可能重新消費之前的所有資料的(視初始消費位置而定)

11. 消息延遲/積壓

消息隊列主要的功能是子產品結偶,同步轉異步和削峰,必然會出現生産非常快但是消費慢這種事情,比如生産的速度是100000/s但是消費速度是1/s,這個時候就叫做消息積壓或者消費延遲(Delay)。理論上RockeMQ對于這種場景有比較好的适應能力,原理大緻這樣:正常的生産消費都是操作記憶體資料,是以比較快。但是如果積壓非常多,記憶體明顯扛不住了,則降級為生産消費的是磁盤資料,直接操作磁盤。磁盤肯定比記憶體的速度慢很多啦。

這個時候整個叢集的處理能力就拉低了。是以最好生産和消費能力不要相差太多,即便相差很多,積壓也應該在有限的時間内處理完畢。

目前比較容易出現消息積壓的情況有:

  • 新消費組上線(消費曆史消息)
  • 消費能力弱
  • 生産洪峰(比如for循環發消息,job發消息)

由于RocketMQ開源版本沒有多租戶隔離,是以公共叢集使用的過程中會有互相影響發生,鑒于此大家在上線前還是要合理評估自己的系統能力。

12. InstanceName

上面說的Producer Group和Consumer Group都是邏輯概念。如果需要連接配接多叢集,就需要實體上進行區分(Instance Name)。

一個Instance Name對應一個連接配接,預設的值是本機ip@程序号。連接配接多叢集的時候務必修改這個值。

三、MQ的使用場景

消息隊列中間件是分布式系統中重要的元件,主要解決應用解耦,異步消息,流量削鋒等問題,實作高性能,高可用,可伸縮和最終一緻性架構。

1. 異步處理

場景說明:使用者注冊後,需要發注冊郵件和注冊短信。傳統的做法有兩種 (1) 串行的方式;(2) 并行方式

注冊郵件,發送短信寫入消息隊列後,直接傳回,縮短了響應時間,提高了吞吐量。

2. 應用解耦

場景說明:使用者下單後,訂單系統需要通知庫存系統。傳統的做法是,訂單系統調用庫存系統的接口。

傳統模式的缺點:假如庫存系統無法通路,則訂單減庫存将失敗,進而導緻訂單失敗,訂單系統與庫存系統耦合。

引入消息隊列後,

訂單系統:使用者下單後,訂單系統完成持久化處理,将消息寫入消息隊列,傳回使用者訂單下單成功。

庫存系統:訂閱下單的消息,采用拉/推的方式,擷取下單資訊,庫存系統根據下單資訊,進行庫存操作。

假如:在下單時庫存系統不能正常使用。也不影響正常下單,因為下單後,訂單系統寫入消息隊列就不再關心其他的後續操作了。實作訂單系統與庫存系統的應用解耦。

3. 流量削峰

流量削鋒也是消息隊列中的常用場景,一般在秒殺或團搶活動中使用廣泛。

應用場景:秒殺活動,一般會因為流量過大,導緻流量暴增,應用挂掉。為解決這個問題,一般需要在應用前端加入消息隊列。

a、可以控制活動的人數。

b、可以緩解短時間内高流量壓垮應用。

使用者的請求,伺服器接收後,首先寫入消息隊列。假如消息隊列長度超過最大數量,則直接抛棄使用者請求或跳轉到錯誤頁面。

秒殺業務根據消息隊列中的請求資訊,再做後續處理

4. 日志處理

日志處理是指将消息隊列用在日志進行中,比如Kafka的應用,解決大量日志傳輸的問題。

日志采集用戶端,負責日志資料采集,定時寫受寫入Kafka隊列。

Kafka消息隊列,負責日志資料的接收,存儲和轉發。

日志處理應用:訂閱并消費kafka隊列中的日志資料 。

時刻與技術進步,每天一點滴,日久一大步!!!

本部落格隻為記錄,用于學習,如有冒犯,請私信于我。