歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)面試
週一至週五早8點半!精品技術文章準時送上!算法
(1)前情提示數據庫
(2)保證投遞消息不丟失的confirm機制性能優化
(3)confirm機制的代碼實現網絡
(4)confirm機制投遞消息的高延遲性架構
(5)高併發下如何投遞消息才能不丟失併發
(6)消息中間件全鏈路100%數據不丟失能作到嗎?異步
上篇文章:《面試大殺器:消息中間件如何實現消費吞吐量的百倍優化?》,咱們分析了RabbitMQ開啓手動ack機制保證消費端數據不丟失的時候,prefetch機制對消費者的吞吐量以及內存消耗的影響。分佈式
經過分析,咱們知道了prefetch過大容易致使內存溢出,prefetch太小又會致使消費吞吐量太低,因此在實際項目中須要慎重測試和設置。微服務
這篇文章,咱們轉移到消息中間件的生產端,一塊兒來看看如何保證投遞到MQ的數據不丟失。
若是投遞出去的消息在網絡傳輸過程當中丟失,或者在RabbitMQ的內存中還沒寫入磁盤的時候宕機,都會致使生產端投遞到MQ的數據丟失。
並且丟失以後,生產端本身還感知不到,同時還沒辦法來補救。
下面的圖就展現了這個問題。
因此本文呢,咱們就來逐步分析一下。
其實要解決這個問題,相信你們看過以前的消費端ack機制以後,也都猜到了。
很簡單,就是生產端(好比上圖的訂單服務)首先須要開啓一個confirm模式,接着投遞到MQ的消息,若是MQ一旦將消息持久化到磁盤以後,必須也要回傳一個confirm消息給生產端。
這樣的話,若是生產端的服務接收到了這個confirm消息,就知道是已經持久化到磁盤了。
不然若是沒有接收到confirm消息,那麼就說明這條消息半路可能丟失了,此時你就能夠從新投遞消息到MQ去,確保消息不要丟失。
並且一旦你開啓了confirm模式以後,每次消息投遞也一樣是有一個delivery tag的,也是起到惟一標識一次消息投遞的做用。
這樣,MQ回傳ack給生產端的時候,會帶上這個delivery tag。你就知道具體對應着哪一次消息投遞了,能夠刪除這條消息。
此外,若是RabbitMQ接收到一條消息以後,結果內部出錯發現沒法處理這條消息,那麼他會回傳一個nack消息給生產端。此時你就會感知到這條消息可能處理有問題,你能夠選擇從新再次投遞這條消息到MQ去。
或者另外一種狀況,若是某條消息很長時間都沒給你回傳ack/nack,那多是極端意外狀況發生了,數據也丟了,你也能夠本身從新投遞消息到MQ去。
經過這套confirm機制,就能夠實現生產端投遞消息不會丟失的效果。你們來看看下面的圖,一塊兒來感覺一下。
下面,咱們再來看看confirm機制的代碼實現:
這裏有一個很關鍵的點,就是一旦啓用了confirm機制投遞消息到MQ以後,MQ是不保證何時會給你一個ack或者nack的。
由於RabbitMQ本身內部將消息持久化到磁盤,自己就是經過異步批量的方式來進行的。
正常狀況下,你投遞到RabbitMQ的消息都會先駐留在內存裏,而後過了幾百毫秒的延遲時間以後,再一次性批量把多條消息持久化到磁盤裏去。
這樣作,是爲了兼顧高併發寫入的吞吐量和性能的,由於要是你來一條消息就寫一次磁盤,那麼性能會不好,每次寫磁盤都是一次fsync強制刷入磁盤的操做,是很耗時的。
因此正是由於這個緣由,你打開了confirm模式以後,極可能你投遞出去一條消息,要間隔幾百毫秒以後,MQ纔會把消息寫入磁盤,接着你纔會收到MQ回傳過來的ack消息,這個就是所謂confirm機制投遞消息的高延遲性。
你們看看下面的圖,一塊兒來感覺一下。
你們能夠考慮一下,在生產端高併發寫入MQ的場景下,你會面臨兩個問題:
一、你每次寫一條消息到MQ,爲了等待這條消息的ack,必須把消息保存到一個存儲裏。
而且這個存儲不建議是內存,由於高併發下消息是不少的,每秒可能都幾千甚至上萬的消息投遞出去,消息的ack要等幾百毫秒的話,放內存可能有內存溢出的風險。
二、絕對不能以同步寫消息 + 等待ack的方式來投遞,那樣會致使每次投遞一個消息都同步阻塞等待幾百毫秒,會致使投遞性能和吞吐量大幅度降低。
針對這兩個問題,相對應的方案其實也呼之欲出了。
首先,用來臨時存放未ack消息的存儲須要承載高併發寫入,並且咱們不須要什麼複雜的運算操做,這種存儲首選絕對不是MySQL之類的數據庫,而建議採用kv存儲。kv存儲承載高併發能力極強,並且kv操做性能很高。
其次,投遞消息以後等待ack的過程必須是異步的,也就是相似上面那樣的代碼,已經給出了一個初步的異步回調的方式。
消息投遞出去以後,這個投遞的線程其實就能夠返回了,至於每一個消息的異步回調,是經過在channel註冊一個confirm監聽器實現的。
收到一個消息ack以後,就從kv存儲中刪除這條臨時消息;收到一個消息nack以後,就從kv存儲提取這條消息而後從新投遞一次便可;也能夠本身對kv存儲裏的消息作監控,若是超過必定時長沒收到ack,就主動重發消息。
你們看看下面的圖,一塊兒來體會一下:
到此爲止,咱們已經把生產端和消費端如何保證消息不丟失的相關技術方案結合RabbitMQ這種中間件都給你們分析過了。
其實,架構思想是通用的, 不管你用的是哪種MQ中間件,他們提供的功能是不太同樣的,可是你都須要考慮以下幾點:
生產端如何保證投遞出去的消息不丟失:消息在半路丟失,或者在MQ內存中宕機致使丟失,此時你如何基於MQ的功能保證消息不要丟失?
MQ自身如何保證消息不丟失:起碼須要讓MQ對消息是有持久化到磁盤這個機制。
消費端如何保證消費到的消息不丟失:若是你處理到一半消費端宕機,致使消息丟失,此時怎麼辦?
目前來講,咱們初步的藉着RabbitMQ舉例,已經把從前到後一整套技術方案的原理、設計和實現都給你們分析了一遍了。
可是此時真的能作到100%數據不丟失嗎?恐怕未必,你們再考慮一下個特殊的場景。
生產端投遞了消息到MQ,並且持久化到磁盤而且回傳ack給生產端了。
可是此時MQ還沒投遞消息給消費端,結果MQ部署的機器忽然宕機,並且由於未知的緣由磁盤損壞了,直接在物理層面致使MQ持久化到磁盤的數據找不回來了。
這個你們千萬別覺得是開玩笑的,你們若是留意留意行業新聞,這種磁盤損壞致使數據丟失的是真的有的。
那麼此時即便你把MQ重啓了,磁盤上的數據也丟失了,數據是否是仍是丟失了?
你說,我能夠用MQ的集羣機制啊,給一個數據作多個副本,好比後面咱們就會給你們分析RabbitMQ的鏡像集羣機制,確實能夠作到數據多副本。
可是即便數據多副本,必定能夠作到100%數據不丟失?
好比說你的機房忽然遇到地震,結果機房裏的機器所有沒了,數據是否是仍是全丟了?
說這個,並非說要擡槓。而是告訴你們,技術這個東西,100%都是理論上的指望。
應該說,咱們凡事都朝着100%去作,可是理論上是不可能徹底作到100%保證的,可能就是作到99.9999%的可能性數據不丟失,可是仍是有千萬分之一的機率會丟失。
固然,從實際的狀況來講,能作到這種地步,其實基本上已經基本數據不會丟失了。
end
若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!
一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上
歡迎掃描下方二維碼,持續關注:
石杉的架構筆記(id:shishan100)
十餘年BAT架構經驗傾囊相授
推薦閱讀:
二、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?
三、【性能優化之道】每秒上萬併發下的Spring Cloud參數優化實戰
六、大規模集羣下Hadoop NameNode如何承載每秒上千次的高併發訪問
七、【性能優化的祕密】Hadoop如何將TB級大文件的上傳性能優化上百倍
九、【坑爹呀!】最終一致性分佈式事務如何保障實際生產中99.99%高可用?
十一、【眼前一亮!】看Hadoop底層算法如何優雅的將大規模集羣性能提高10倍以上?
1六、億級流量系統架構之如何設計全鏈路99.99%高可用架構
1八、大白話聊聊Java併發面試問題之volatile究竟是什麼?
1九、大白話聊聊Java併發面試問題之Java 8如何優化CAS性能?
20、大白話聊聊Java併發面試問題之談談你對AQS的理解?
2一、大白話聊聊Java併發面試問題之公平鎖與非公平鎖是啥?
2二、大白話聊聊Java併發面試問題之微服務註冊中心的讀寫鎖優化
2三、互聯網公司的面試官是如何360°無死角考察候選人的?(上篇)
2四、互聯網公司面試官是如何360°無死角考察候選人的?(下篇)
2五、Java進階面試系列之一:哥們,大家的系統架構中爲何要引入消息中間件?
2六、【Java進階面試系列之二】:哥們,那你說說系統架構引入消息中間件有什麼缺點?
2七、【行走的Offer收割機】記一位朋友斬獲BAT技術專家Offer的面試經歷
2八、【Java進階面試系列之三】哥們,消息中間件在大家項目裏是如何落地的?
2九、【Java進階面試系列之四】扎心!線上服務宕機時,如何保證數據100%不丟失?
30、一次JVM FullGC的背後,竟隱藏着驚心動魄的線上生產事故!
3一、【高併發優化實踐】10倍請求壓力來襲,你的系統會被擊垮嗎?
3二、【Java進階面試系列之五】消息中間件集羣崩潰,如何保證百萬生產數據不丟失?
3三、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(上)?
3四、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(中)?
3五、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(下)?
3七、億級流量系統架構之如何保證百億流量下的數據一致性(上)
3八、億級流量系統架構之如何保證百億流量下的數據一致性(中)?
3九、億級流量系統架構之如何保證百億流量下的數據一致性(下)?
40、互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(1)
4一、互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(2)
做者:石杉的架構筆記 連接:juejin.im/post/5c263a… 來源:掘金 著做權歸做者全部,轉載請聯繫做者得到受權!