RocketMQ:消息存儲

通常來說我們對分布式隊列有高可靠性的要求,所以數據要進行持久化存儲。

  1. 消息生產者發送消息到MQ。
  2. MQ收到消息,將消息進行持久化,即在存儲系統中新增一條記錄。
  3. 返回ACK確認消息給生產者。
  4. 然后MQ推送消息給對應的消費者,等待消費者返回ACK。
  5. 如果消息消費者在指定時間內成功返回ACK,那么MQ認為消息消費成功,在存儲系統中刪除消息,即執行第6步;如果MQ在指定時間內沒有收到ACK,則認為消息消費失敗,會嘗試重新推送消息,重復執行4、5、6步驟。

1. 存儲介質

  • 關系型數據庫DB

存儲系統可選用JDBC的方式來做消息持久化,通過簡單的xml配置信息即可實現JDBC消息存儲。由于普通關系型數據庫(如Mysql)在單表數據量達到千萬級別的情況下,其IO讀寫性能往往會出現瓶頸。在可靠性方面,該種方案非常依賴DB,如果一旦DB出現故障,則MQ的消息就無法落盤存儲會導致線上故障。

  • 文件系統

目前業界較為常用的幾款產品(RocketMQ/Kafka/RabbitMQ)均采用的是消息刷盤至所部署虛擬機/物理機的文件系統來做持久化(刷盤一般可以分為異步刷盤和同步刷盤兩種模式)。消息刷盤為消息存儲提供了一種高效率、高可靠性和高性能的數據持久化方式。除非部署MQ機器本身或是本地磁盤掛了,否則一般是不會出現無法持久化的故障問題。

性能對比:文件系統>關系型數據庫DB

2. 消息的存儲和發送

2.1 消息存儲

目前的高性能磁盤,順序寫速度可以達到600MB/s, 超過了一般網卡的傳輸速度。但是磁盤隨機寫的速度只有大概100KB/s,和順序寫的性能相差6000倍!因為有如此巨大的速度差別,好的消息隊列系統會比普通的消息隊列系統速度快多個數量級。RocketMQ的消息用順序寫,保證了消息存儲的速度。

2.2 消息發送

Linux操作系統分為【用戶態】和【內核態】,文件操作、網絡操作需要涉及這兩種形態的切換,免不了進行數據復制。

一臺服務器把本機磁盤文件的內容發送到客戶端,一般分為兩個步驟:

1)read:讀取本地文件內容;

2)write:將讀取的內容通過網絡發送出去。

這兩個看似簡單的操作,實際進行了4 次數據復制,分別是:

  1. 從磁盤復制數據到內核態內存;
  2. 從內核態內存復制到用戶態內存;
  3. 然后從用戶態內存復制到網絡驅動的內核態內存;
  4. 最后是從網絡驅動的內核態內存復 制到網卡中進行傳輸。

通過使用mmap的方式,可以省去向【用戶態】的內存復制,提高速度。這種機制在Java中是通過MappedByteBuffer實現的。

RocketMQ充分利用了上述特性,也就是所謂的“零拷貝”技術,提高消息存盤和網絡發送的速度。

這里需要注意的是,采用MappedByteBuffer這種內存映射的方式有幾個限制,其中之一是一次只能映射1.5~2G 的文件至用戶態的虛擬內存,這也是為何RocketMQ默認設置單個CommitLog日志數據文件為1G的原因了。

3. 消息存儲結構

RocketMQ消息的存儲是由ConsumeQueue和CommitLog配合完成的,消息真正的物理存儲文件是CommitLog,ConsumeQueue是消息的邏輯隊列,類似數據庫的索引文件,存儲的是指向物理存儲的地址。每 個Topic下的每個Message Queue都有一個對應的ConsumeQueue文件。

  • CommitLog:存儲消息的元數據。
  • ConsumerQueue:存儲消息在CommitLog的索引。
  • IndexFile:為了消息查詢提供了一種通過key或時間區間來查詢消息的方法,這種通過IndexFile來查找消息的方法不影響發送與消費消息的主流程。

4. 刷盤機制

RocketMQ的消息是存儲到磁盤上的,這樣既能保證斷電后恢復, 又可以讓存儲的消息量超出內存的限制。RocketMQ為了提高性能,會盡可能地保證磁盤的順序寫。消息在通過Producer寫入RocketMQ的時候,有兩種寫磁盤方式,分布式同步刷盤和異步刷盤。

4.1 同步刷盤

在返回寫成功狀態時,消息已經被寫入磁盤。具體流程是,消息寫入內存的PAGECACHE后,立刻通知刷盤線程刷盤, 然后等待刷盤完成,刷盤線程執行完成后喚醒等待的線程,返回消息寫成功的狀態。

提醒:還記得在《Redis:持久化之AOF》
中我們也說到,由于操作系統的緩存機制,數據并沒有真正地立即寫入磁盤,而是進入系統的磁盤緩存。

4.2 異步刷盤

在返回寫成功狀態時,消息可能只是被寫入了內存的PAGECACHE,寫操作的返回快,吞吐量大;當內存里的消息量積累到一定程度時,統一觸發寫磁盤動作,快速寫入。

4.3 配置

不管是同步刷盤還是異步刷盤,都是通過Broker配置文件里的flushDiskType參數設置的,這個參數被配置成SYNC_FLUSH、ASYNC_FLUSH中的 一個。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373