自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

RocketMQ在存儲架構上的極致追求

存儲 存儲架構
MQ作為一款中間件,就需要承載全公司所有業(yè)務系統(tǒng)使用需求,并高效穩(wěn)定運行。因此,MQ對本身運行效率有著非??量痰脑V求。本文就RocketMQ為了實現高效的讀寫速率在存儲架構上所做的努力,進行下闡述。

Part one / 存儲結構選型對比

為了更方便的進行數據讀寫,消息在磁盤底層的文件目錄設計,都需要關注和解決什么問題呢:

  • 首先,最基本的,消息原始記錄的寫入和存儲,且速率要快。
  • 其次,要可以區(qū)分topic ,特別是允許消費者按topic進行接收。
  • 再次,分布式集群下的多消費者負載均衡。

那么問題來了,消息文件該怎么設計呢?如果按topic來拆分文件進行存儲,是否可以?

  • 缺點:生產者寫入時選擇對應的文件來寫入。當數據量逐漸增大之后,定位查詢文件地址,對磁盤的尋址所帶來的性能損耗,將不再可以忽略。
  • 優(yōu)點:在消費時,可以直接加載相關文件進行讀取,不會產生隨機尋址。

如果用一整個文件來存消息呢?

  • 優(yōu)點:所有的topic都被寫入一個文件中,這樣,寫入時,只要將消息按到達順序序追加到文件尾部即可,很容易實現順序寫入。
  • 缺點:消費時,需要根據輔助信息來在文件中定位消息,會產生隨機讀,損耗性能。

因此,不管是按topic拆開多文件存儲,還是一整個文件存儲做有利有弊,需要按實際需要進行權衡。

Part two / RocketMQ的存儲方案選擇

RocketMQ存儲原始消息選擇的是寫同一個文件。

生產者將消息順序寫入commitLog文件究其原因,是由于RocketMQ一般都是普通業(yè)務場景使用居多,生產者和topic眾多,如果都獨立開各自存儲,每次消息生產的磁盤尋址對性能損耗是非常巨大的。

旁證側引:

kafka的文件存儲方式,是按topic拆分成partation來進行的。是什么樣的原因,讓kafka做出了和RocketMQ相反的選擇呢?

個人認為,主要還是使用場景的區(qū)別,kafka被優(yōu)先選擇用來進行大數據處理,相對于業(yè)務場景,數據維度的topic要少很多,并且kafka的生產者(spark flume binlog等)機器會更加集中,這使得kafka選擇按topic拆分文件的缺陷不那么突出,而大數據處理更重要的是消息讀取,順序讀的優(yōu)勢得以被充分利用。

"單partation,單cunsumer的kafka,性能異常的優(yōu)秀" 是經常被提及的一個觀點,其原因,相信有了上面的分析應該也差不多有結論了。

Part three / RocketMQ怎樣平衡讀性能

從第一部分的存儲方案對比可以知道,RocketMQ為了保證消息寫入效率,在存儲結構上選擇了順序寫,勢必會對消息的讀取和消費帶來不便。那么,它是怎么來平衡消費時的讀取速率的呢?關鍵問題是,找到一種途徑,可以快速的在commitLog中定位到所需消息的位置。從一堆數據中,快速定位想要的數據,這不是索引最擅長的事情么?所以,RocketMQ也為commitLog創(chuàng)建了索引文件,并且是區(qū)分topic的結構。

存儲架構和存儲構建鏈路示意圖

RocketMQ 的消息體構成

消息體元素構成

  • topic 是業(yè)務場景的唯一標識,不可缺少;
  • queueId 在申請topic的時候確定,關聯著消費索引consumerQueue中的隊列ID;
  • tags 是消息特殊標簽,用于業(yè)務系統(tǒng)訂閱時提前過濾(這個功能真的是太重要了,吃過苦的同學都清楚);
  • keys 是消息的關鍵字,構建index索引,用于關鍵字查詢用;
  • msgBody 是真實消息體;

消息由發(fā)布者發(fā)布,并依次的、順序的寫到commitLog里,消息一旦被寫入,是不可以更改順序和內容的。commitLog規(guī)定最大1個G,達到規(guī)定大小則寫新的一個文件。

索引結構和構建過程

consumerQueue結構和創(chuàng)建過程

consumerQueue 是一種機制,可以讓消費端通過queue和commitLog之間的檢索關系,快速定位到commitLog里邊的具體消息內容,然后拉取進行消費。consumerQueue 按 topic的不同,被分為不同的queue,根據queueId來被消費者訂閱和消費;其中每個索引項是一個固定大小為20bytes的記錄,由消息在commitLog中的起始偏移量、消息體占用大小、type的hash碼三部分構成??梢酝ㄟ^這三個部分快速定位到所需消息位置和類型。而上述索引的構建過程,是在消息被寫入commitLog時,專門的后臺服務--putMessageService,將索引信息分發(fā)到 consumerQueue 和index文件里,來構建索引項。建索引的過程,實際上是一種分而治之思維的落地,除了索引,還有redis中的各種指標維護,核心是 分散壓力到每次請求,避免了大規(guī)模集中計算。

消息的消費

消費者對應consumerQueue不一定是一對一的,因此,怎么來讓每個新的消費者來了不會重復消費呢?

offset消費位點記錄在消息成功被拉取并消費時,后臺任務CommitOffsetManager 會將當前消費者,針對topic的消費位點進行記錄,目的是讓下一個或者重新啟動單餓消費者記住這個消費位點,不至于重復消費。因此,整個文件目錄就一目了然了:

Part four / 讀效率的追求

雖然通過上述文件存儲結構的分析,我們知道,消費者可以根據索引文件中的索引項來快速定位, 但事實上,消息的發(fā)布和消費,不可能直接針對磁盤進行讀寫操作的,這樣效率會非常非常低。

實際上,我們的操作基本是針對一塊內存進行操作的 。

利用NIO的內存映射機制,我們將commitLog的一部分文件交換到對外內存。然后利用操作系統(tǒng)的pageCache技術,在運行過程中把內存里的信息,與磁盤里的文件信息進行同步,或者交換:

  • 消息發(fā)布者,在發(fā)布消息的時候,首先把消息添加到內存里,然后根據刷盤的配置可以來指定是同步刷盤還是異步刷盤,來將內存中的數據同步到磁盤上。
  • 消息的消費者,在消費消息的時候,大多數情況下,會直接命中到內存上,不會進行磁盤讀,但極個別的情況下,需要消費的消息,在內存中沒法找到,這時候,就需要用換頁技術,將相關的信息,拉取到內存中。為什么是相關信息,而不是需要什么拉取什么?這是有一個機制,來保證潛在的即將被消費的信息直接換入內存,來提交效率。

摘自:Qcon大會 RocketMQ分享資料

Part five / 總結

整體一套處理流程看下來,其實我們可以看到很多熟悉的身影,比如Mysql的索引,redis的統(tǒng)計信息記錄等等,都非常相似。其實,我們可以這么認為:對于信息存儲和查詢的處理方案大都如出一轍,只要把握住最核心的部分,然后根據實際業(yè)務訴求進行適配優(yōu)化,基本都是可以達到期望的結果的。


責任編輯:武曉燕 來源: Coder的技術之路
相關推薦

2025-04-10 06:00:00

2013-07-31 09:25:47

用戶體驗產品經理

2023-05-04 10:43:42

Qwik前端框架

2019-07-23 09:20:15

Kafka批量處理客戶端

2018-10-29 15:41:16

二手硬件處理器

2012-03-05 16:28:24

華碩筆記本

2020-08-28 11:20:01

CentOS7RocketMQ 4.運維

2015-06-02 11:24:06

容聯云通訊

2021-09-02 16:10:57

系統(tǒng)數據存儲

2019-07-12 14:41:31

微服務Kubernetes容器

2012-04-11 13:42:53

ibmdw

2018-01-29 09:42:27

創(chuàng)業(yè)技術團隊

2021-07-09 07:15:48

RocketMQ數據結構kafka

2012-09-29 13:33:16

Squid圖片存儲存儲架構

2022-12-31 08:17:02

2012-06-26 10:35:40

Squid架構

2022-02-23 15:08:18

開發(fā)分布式Java

2013-12-18 13:15:36

算法

2021-07-07 15:29:52

存儲RocketMQ體系

2022-10-11 09:05:58

IPFS區(qū)塊鏈存儲
點贊
收藏

51CTO技術棧公眾號