RocketMQ簡介

簡介

 

rocketMQ是一款分佈式、消息隊列中間件。基於發佈訂閱模式,有Push和Pull兩種消費方式,支持嚴格的消息順序,億級別的堆積能力,支持消息回溯和多個維度的消息查詢。
核心作用:解耦、異步化、消息堆積緩衝

 

 

高性能離不開異步,異步離不開隊列!

 

 

基本概念

 

Producer: 消息生產者,負責產生消息併發送消息到meta服務器
Consumer: 消息消費者,負責消費消息,一般是後臺系統負責異步消費。
Broker:  Metaq的服務器。
Topic:   消息的主題,由用戶定義並在服務端配置
Message: 在生產者,消費者,服務器間傳遞的消息
Group:  消費者分組。消費者可以是多個消費者共同消費一個 topic 下的消息,每個消費者消費部分消息。這些消費者就組成一個分組,擁有同一個分組名稱,通常也稱爲消費者集羣。
Offset:  消息在服務器上的每個分區都是組織成一個文件列表,消費者拉取數據需要知道數據在文件中的偏移量。

 

 

 

 

架構圖

 

 

 

 

主要消費流程

 

1、Producer:生產者首先向NameService拉取Topic相關的所有Broker,然後以RobinRound方式發送消息。

 

 

2、Broker:消息進入Broker後,先寫入CommitLog裏。同時會將該消息在文件的物理位置,消息大小,消息類型封裝成一個固定大小的數據結構,稱爲索引單元。然後異步寫入到ConsumerQueue中。

 

3、Consumer:消費者採取拉模式向一臺Broker請求Topic信息,然後進行Reblance操作,計算自己負責的隊列,然後消費。廣播模式下消費進度存儲在本地,單播模式下存儲在Broker。

 

 

 

具體消費過程

 

消費端拉取消息時,至少需要以下幾個參數

 

  1. 消息主題
  2. 邏輯隊列序號
  3. 索引起始位置
  4. 消息最大長度
  5. 當前請求序列號
  6. 消費者分組名稱


服務器收到請求後

 

  1. 根據 topic 和 partition 找到邏輯隊列:A
  2. 根據 offset 從 A 定位指定的索引文件:B
  3. 從 B 中讀取所有的索引數據:C
  4. 遍歷 C,根據索引單元的消息物理地址和消息長度,找到物理消息 D(二分遍歷),將 D 放入集合,並計算消息的累加長度,若大於請求裏消息最大長度 maxSize,則終止遍歷,返回結果。

 

 

 

消息結果裏有當前批次消息的索引讀取結束位置(offset),消費端會將當前 offset 。存儲在本地,下次拉取消息時,要將結束位置作爲參數放入消息拉取請求裏。由於 metaq 是分佈式結構,消費端和生產端的對應關係可能會經常變動,offset 不能僅僅只是保存到本地,必須保存在一個共享的存儲裏,比如zookeeper,數據庫,或共享的文件系統。默認情況下,metaq 將offset及時保存在本地,並定時寫入zookeeper。在某些情況下,會發生消息重複消費,比如某個 consumer 掛掉了,新的consumer將會接替它繼續消費,但是 offset是異步存儲的,可能新的 consumer 起來後,從zookeeper上拿到的還是舊的 offset,導致當前批次重複,產生重複消費。

 

 

 

 

 

負載均衡

 

 

一個邏輯分區實際上是一組索引文件。一個 topic 在一個 broker 上可以有多個邏輯分區,默認爲 1,但可自由配置。


一個topic可以分佈在多臺broker上,具體體現就是多個broker配置了這個topic,並且最少有一個分區。假如有一個topic名爲”t1”,兩個broker:b1,b2;每個 borker 都爲 t1 配置了兩個分區。那麼 t1 一共有4個分區:b1-1,b1-2,b2-1,b2-2。生產者和消費者對topic發佈消息或消費消息時,目的地都是以分區爲單位。當一個topic消息量逐漸變大時,可以將 topic 分佈在更多的 borker 上。某個 broker上的分區數越多,意味着該 borker承擔更繁重的任務,分區數可以認爲是權重的表現形式。

 

 

生產者負載均衡

 

 

生產者在通過 zk 獲取分區列表之後,會按照 brokerId 和分區號的順序排列組織成一個有序的分區列表,發送的時候按照從頭到尾循環往復的方式選擇一個分區來發送消息(可通過實現PartitionSelector接口改寫負載均衡算法)

在broker 因爲重啓或者故障等因素無法服務的時候,producer 通過 zookeeper 會感知到這個變化,將失效的分區從列表中移除。從故障到感知變化有一個延遲,可能在那一瞬間會有部分的消息發送失敗。

 

 

消費者負載均衡

 

 

 

 

 

單個分組內的消費者數目如果比總的分區數目多的話,則多出來的消費者不參與消費


如果分組內的消費者數目比分區數目小,則有部分消費者要額外承擔消息的費任務 

 

 

 

 

 

性能問題

commit-log隊列採取順序添加的方式(200M 每秒),對磁盤的訪問串行化,避免磁盤竟爭(但是讀卻變成了完全的隨機讀,不過可以通過PAGECACHE優化掉)。

 

前面說的隊列存儲都是保存到文件中,頻繁的IO操作會降低性能。通過把文件的內容被映像到計算機虛擬內存的一塊區域(mmap),這樣就可以直接操作內存當中的數據而無需操作的時候每次都通過 I/O 去物理硬盤讀取文件,從而效率上有很大的提升。


修改不一定會立即同步到文件系統中。如果在沒有同步之前發生了程序錯誤,可能導致所做的修改丟失。因此,在執行完某些重要文件內容的更新操作之後,應該調用相應方法來強制要求把這些更新同步到底層文件中

metaq 的消費模型是拉模式。而且拉取完一批消息,消費完畢,再去拉取下一批,而不是一條一條拉取,這裏存在實時性和性能的權衡。

 

 

 

當消息堆積時,1K 大小左右消息體堆積情況下吞吐量非常高,在 5W 每秒以上。4K 消息性能最差,1W 每秒左右。

 

 

可靠性保證

生產者發送消息後返回 SendResult,如果 isSuccess 返回爲 true,則表示消息已經確認發送到服務器並被服務器接收存儲。整個發送過程是一個同步的過程。保證消息送達服務器並返回結果。

服務器收到後在做必要的校驗和檢查之後的第一件事就是寫入磁盤(這裏只是寫入了系統緩存,存在緩存到磁盤的刷新過程),寫入成功之後返回應答給生產者。

 

 

 

 

 

數據過濾

MetaQ支持兩種過濾方式:服務器端過濾,客戶端過濾。
服務器過濾:減少網絡上無用消息的傳輸,但是會增加服務器負擔。
客戶端過濾:根據客戶端需求來定製消息,缺點是很多無用消息都會傳到客戶端,如果客戶端無法負載這麼多消息就會導致故障問題。
 

實戰優化

sysctl -w vm.min_free_kbytes=20000000

consume.thread.max=64 //無效
consume.thread.min=64 //設置min,並且兩者相同



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章