【Java進階面試系列之四】扎心!線上服務宕機時,如何保證數據100%不丟失?【石杉的架構筆記】

歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)
面試

週一至週五早8點半!精品技術文章準時送上!算法


1、寫在前面

上篇文章「Java進階面試系列之三」消息中間件在大家項目裏是如何落地的?,咱們用一個簡單易懂的電商場景給你們引入說明了一個消息中間件的使用場景。性能優化

同時,咱們還基於RabbitMQ的HelloWorld級別的代碼,給出了訂單服務和倉儲服務如何基於MQ中間件收發消息的示例。架構


2、業務場景回顧

這篇文章,咱們來稍微深刻探討一些MQ中間件使用中的基礎技術問題。併發

首先回顧一下上篇文章作出來的一個架構圖,看看訂單服務和消息服務是如何基於MQ來收發消息的。iphone

咱們稍微把這個圖細化一點,簡單來講就是多個訂單服務實例給queue推送消息,多個倉儲服務每一個消費一部分消息。以下圖所示:分佈式


3、意外宕機,問題凸現

假如你線上對MQ技術的使用就到此爲止了,那麼基本能夠跟offer說拜拜了。。。微服務

由於若是是個人話,做爲一個面試官就無法繼續往下問了。你這個MQ的使用以及理解的深度僅此而已的話,那基本就是剛剛對MQ技術入門的程度。高併發

若是面試官要繼續問,徹底能夠問下面的問題:oop

  • 那你說說若是倉儲服務做爲消費者服務,剛收到了一個訂單消息,可是在完成消息的處理以前,也就是還沒對訂單完成倉儲調度發貨,結果這個倉儲服務忽然就宕機了,這個時候會發生什麼事情?


因此說,你們仍是要對這個技術瞭解的稍微深刻一點點,不然隨便被問幾個問題就完蛋了。

大夥兒先來看看下面的圖,感覺一下車禍現場。

RabbitMQ這個中間件默認的一個行爲,就是隻要倉儲服務收到一個訂單消息,RabbitMQ就會立馬把這條訂單消息給標記爲刪除,這個行爲叫作自動ack,也就是投遞完成一條消息就自動確認這個消息處理完畢了。

可是接着若是此時倉儲服務收到了一個訂單消息,可是還沒來得及對倉庫系統完成商品的調度發貨,結果直接就宕機了。

此時,明顯這個訂單消息就丟失了啊,由於RabbitMQ那裏已經沒有了。。。

這會致使什麼樣的尷尬體驗呢?就是一個用戶支付了8999元,對一個iphone8下了訂單,結果呢,死等活等了好幾天,就是不見網站上顯示他的iphone8在發貨。

搞了半天,緣由就是他的那個iphone8的訂單在倉儲服務那裏,還沒來得及調度發貨直接就宕機了,致使這個訂單消息就一直丟失了,始終沒有給這個用戶通知倉庫系統進行發貨。

這個問題,是否是很尷尬?因此說,技術問題是會嚴重影響企業的核心業務流程的!

各位小夥伴,還記得上一講我們的倉儲服務消費消息的代碼中,有一行關鍵的代碼:

這行代碼對channel.basicConsume()方法,傳入的第二個參數:true,其實就是一個關鍵的參數。

這個true就表明了一個核心的含義,他的意思是,RabbitMQ只要把一個消息投遞到倉儲服務手上,立馬就標記這個消息刪除了。

可是在這個默認的配置之下,要是倉儲服務收到一個訂單消息,結果還沒來得及完成耗時幾十秒的倉儲調度發貨的業務邏輯,結果忽然宕機了,那麼這個訂單消息就永久性丟失了!

找了半天,原來問題的癥結在這裏啊!你們是否是明白了,上一篇文章最後爲何我會說,這個代碼目前爲止還有不少的問題。

因此這個時候,咱們若是但願不要由於倉儲服務的忽然宕機致使一條訂單消息丟失,就須要改造一下倉儲服務消費消息的代碼了。

首先,咱們須要把那個參數從true改成false,以下代碼所示:

只要修改成false以後,RabbitMQ就不會盲目的投遞消息到倉儲服務,立馬就刪除消息了,說白了就是關閉autoAck的行爲,不要自做主張的認爲消息處理成功了。

接着,咱們須要改造一下處理訂單消息的代碼,以下代碼所示。

這段代碼,說白了,就是在對訂單完成了調度發貨以後,在finally代碼塊中手動執行了ack操做,說我本身已經完成了耗時幾十秒的業務邏輯的處理,如今能夠手動ack通知RabbitMQ,這個消息處理完畢了。

此時整個架構運行流程大體看起來跟下面的圖那樣子。

架構流程改爲上面那樣後,就意味着只有完成了倉儲調度發貨的代碼業務邏輯,確保倉庫系統收到通知以後,倉儲服務纔會在代碼中手動發送ack消息給RabbitMQ。

此時,RabbitMQ收到了這個ack消息,纔會標記對應的訂單消息被刪除了。

若是說在倉儲服務收到了訂單消息,可是還沒來得及完成倉儲調度發貨的業務邏輯,那也就絕對不會執行這條訂單消息的ack操做,而後RabbitMQ也就不會收到這條訂單消息的ack通知。

一旦RabbitMQ發現表明消費者的某個倉儲服務實例忽然宕機了,而這個倉儲服務收到的一些訂單消息還沒來得及處理,沒給本身發送那些消息的ack通知。

此時,RabbitMQ會自動對這條訂單消息重發推送給其餘在運行中的倉儲服務實例,讓其餘的倉儲服務實例去處理這條訂單消息。

這樣的話,就能夠保證這條訂單消息不會由於某個倉儲服務實例的宕機而丟失,他會確保必須由某個倉儲服務實例完成這條訂單消息的調度發貨處理,而後纔會刪除那條訂單消息。


4、總結 tips

最後再來一張圖,你們直觀的感覺一下:

好了,各位同窗,這篇文章是否是相對稍微深刻一點點,讓你們瞭解到了一些使用MQ技術時候要考慮的一些問題?

實際上不管是RocketMQ、Kafka仍是RabbitMQ,都有相似的autoAck或者是手動ack的機制。

線上生產環境中運行時,你必需要考慮到消費者服務可能宕機的問題。

若是消費者服務沒處理完消息就本身宕機了,那麼必定會致使部分消息的丟失,進而影響核心業務流程的運轉。

所以你們在線上使用MQ時,必定要充分考慮這些潛在問題,同時結合具體的MQ提供的一些API、參數來進行合理設置,確保消息不要隨意丟失。

END


若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!


一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上

歡迎掃描下方二維碼,持續關注:


石杉的架構筆記(id:shishan100)

十餘年BAT架構經驗傾囊相授


推薦閱讀:

一、拜託!面試請不要再問我Spring Cloud底層原理

二、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?

三、【性能優化之道】每秒上萬併發下的Spring Cloud參數優化實戰

四、微服務架構如何保障雙11狂歡下的99.99%高可用

五、兄弟,用大白話告訴你小白都能聽懂的Hadoop架構原理

六、大規模集羣下Hadoop NameNode如何承載每秒上千次的高併發訪問

七、【性能優化的祕密】Hadoop如何將TB級大文件的上傳性能優化上百倍

八、拜託,面試請不要再問我TCC分佈式事務的實現原理坑爹呀!

九、【坑爹呀!】最終一致性分佈式事務如何保障實際生產中99.99%高可用?

十、拜託,面試請不要再問我Redis分佈式鎖的實現原理!

十一、【眼前一亮!】看Hadoop底層算法如何優雅的將大規模集羣性能提高10倍以上?

十二、億級流量系統架構之如何支撐百億級數據的存儲與計算

1三、億級流量系統架構之如何設計高容錯分佈式計算系統

1四、億級流量系統架構之如何設計承載百億流量的高性能架構

1五、億級流量系統架構之如何設計每秒十萬查詢的高併發架構

1六、億級流量系統架構之如何設計全鏈路99.99%高可用架構

1七、七張圖完全講清楚ZooKeeper分佈式鎖的實現原理

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進階面試系列之三】哥們,消息中間件在大家項目裏是如何落地的?

相關文章
相關標籤/搜索