歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)面試
週一至週五早8點半!精品技術文章準時送上!算法
(1)前請提示性能優化
(2)unack消息的積壓問題架構
(3)如何解決unack消息的積壓問題併發
(4)高併發場景下的內存溢出問題異步
(5)低吞吐量問題分佈式
(6)合理設置prefetch count微服務
(7)階段性總結高併發
上一篇文章:互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(2),咱們分析了ack機制的底層實現原理(delivery tag機制),還有消除處理失敗時的nack機制如何觸發消息重發。oop
經過這個,已經讓你們進一步對消費端保證數據不丟失的方案的理解更進一層了。
這篇文章,咱們將會對ack底層的delivery tag機制進行更加深刻的分析,讓你們理解的更加透徹一些。
面試時,若是被問到消息中間件數據不丟失問題的時候,能夠更深刻到底層,給面試官進行分析。
首先,咱們要給你們介紹一下RabbitMQ的prefetch count這個概念。
你們看過上篇文章以後應該都知道了,對每一個channel(其實對應了一個消費者服務實例,你大致能夠這麼來認爲),RabbitMQ投遞消息的時候,都是會帶上本次消息投遞的一個delivery tag的,惟一標識一次消息投遞。
而後,咱們進行ack時,也會帶上這個delivery tag,基於同一個channel進行ack,ack消息裏會帶上delivery tag讓RabbitMQ知道是對哪一次消息投遞進行了ack,此時就能夠對那條消息進行刪除了。
你們先來看一張圖,幫助你們回憶一下這個delivery tag的概念。
因此你們能夠考慮一下,對於每一個channel而言(你就認爲是針對每一個消費者服務實例吧,好比一個倉儲服務實例),其實都有一些處於unack狀態的消息。
好比RabbitMQ正在投遞一條消息到channel,此時消息確定是unack狀態吧?
而後倉儲服務接收到一條消息之後,要處理這條消息須要耗費時間,此時消息確定是unack狀態吧?
同時,即便你執行了ack以後,你要知道這個ack他默認是異步執行的,尤爲若是你開啓了批量ack的話,更是有一個延遲時間纔會ack的,此時消息也是unack吧?
那麼你們考慮一下,RabbitMQ他可以無限制的不停給你的消費者服務實例推送消息嗎?
明顯是不能的,若是RabbitMQ給你的消費者服務實例推送的消息過多過快,好比都有幾千條消息積壓在某個消費者服務實例的內存中。
那麼此時這幾千條消息都是unack的狀態,一直積壓着,是否是有可能會致使消費者服務實例的內存溢出?內存消耗過大?甚至內存泄露之類的問題產生?
因此說,RabbitMQ是必需要考慮一下消費者服務的處理能力的。
你們看看下面的圖,感覺一下若是消費者服務實例的內存中積壓消息過多,都是unack的狀態,此時會怎麼樣。
正是由於這個緣由,RabbitMQ基於一個prefetch count來控制這個unack message的數量。
你能夠經過 「channel.basicQos(10)」 這個方法來設置當前channel的prefetch count。
舉個例子,好比你要是設置爲10的話,那麼意味着當前這個channel裏,unack message的數量不能超過10個,以此來避免消費者服務實例積壓unack message過多。
這樣的話,就意味着RabbitMQ正在投遞到channel過程當中的unack message,以及消費者服務在處理中的unack message,以及異步ack以後還沒完成ack的unack message,全部這些message加起來,一個channel也不能超過10個。
若是你要簡單粗淺的理解的話,也大體能夠理解爲這個prefetch count就表明了一個消費者服務同時最多能夠獲取多少個message來處理。因此這裏也點出了prefetch這個單詞的意思。
prefetch就是預抓取的意思,就意味着你的消費者服務實例預抓取多少條message過來處理,可是最多隻能同時處理這麼多消息。
若是一個channel裏的unack message超過了prefetch count指定的數量,此時RabbitMQ就會中止給這個channel投遞消息了,必需要等待已經投遞過去的消息被ack了,此時才能繼續投遞下一個消息。
老規矩,給你們上一張圖,咱們一塊兒來看看這個東西是啥意思。
好!如今你們對ack機制底層的另一個核心機制:prefetch機制也有了一個深入的理解了。
此時,我們就應該來考慮一個問題了。就是如何來設置這個prefetch count呢?這個東西設置的過大或者太小有什麼影響呢?
其實你們理解了上面的圖就很好理解這個問題了。
假如說咱們把prefetch count設置的很大,好比說3000,5000,甚至100000,就這樣特別大的值,那麼此時會如何呢?
這個時候,在高併發大流量的場景下,可能就會致使消費者服務的內存被快速的消耗掉。
由於假如說如今MQ接收到的流量特別的大,每秒都上千條消息,並且此時你的消費者服務的prefetch count還設置的特別大,就會致使可能一瞬間你的消費者服務接收到了達到prefetch count指定數量的消息。
打個比方,好比一會兒你的消費者服務內存裏積壓了10萬條消息,都是unack的狀態,反正你的prefetch count設置的是10萬。
那麼對一個channel,RabbitMQ就會最多容忍10萬個unack狀態的消息,在高併發下也就最多可能積壓10萬條消息在消費者服務的內存裏。
那麼此時致使的結果,就是消費者服務直接被擊垮了,內存溢出,OOM,服務宕機,而後大量unack的消息會被從新投遞給其餘的消費者服務,此時其餘消費者服務同樣的狀況,直接宕機,最後形成雪崩效應。
全部的消費者服務由於扛不住這麼大的數據量,所有宕機。
你們來看看下面的圖,本身感覺一下現場的氛圍。
那麼若是反過來呢,咱們要是把prefetch count設置的很小會如何呢?
好比說咱們把prefetch count設置爲1?此時就必然會致使消費者服務的吞吐量極低。由於你即便處理完一條消息,執行ack了也是異步的。
給你舉個例子,假如說你的prefetch count = 1,RabbitMQ最多投遞給你1條消息處於unack狀態。
此時好比你剛處理完這條消息,而後執行了ack的那行代碼,結果不幸的是,ack須要異步執行,也就是須要100ms以後纔會讓RabbitMQ感知到。
那麼100ms以後RabbitMQ感知到消息被ack了,此時纔會投遞給你下一條消息!
這就尷尬了,在這100ms期間,你的消費者服務是否是啥都沒幹啊?
這不就直接致使了你的消費者服務處理消息的吞吐量可能降低10倍,甚至百倍,千倍,都有這種可能!
你們看看下面的圖,感覺一下低吞吐量的現場。
因此鑑於上面兩種極端狀況,RabbitMQ官方給出的建議是prefetch count通常設置在100~300之間。
也就是一個消費者服務最多接收到100~300個message來處理,容許處於unack狀態。
這個狀態下能夠兼顧吞吐量也很高,同時也不容易形成內存溢出的問題。
可是其實在咱們的實踐中,這個prefetch count你們徹底是能夠本身去壓測一下的。
好比說慢慢調節這個值,不斷加大,觀察高併發大流量之下,吞吐量是否愈來愈大,並且觀察消費者服務的內存消耗,會不會OOM、頻繁FullGC等問題。
其實經過最近幾篇文章,基本上已經把消息中間件的消費端如何保證數據不丟失這個問題剖析的較爲深刻和透徹了。
若是你是基於RabbitMQ來作消息中間件的話,消費端的代碼裏,必須考慮三個問題:手動ack、處理失敗的nack、prefetch count的合理設置
這三個問題背後涉及到了各類機制:
自動ack機制
delivery tag機制
ack批量與異步提交機制
消息重發機制
手動nack觸發消息重發機制
prefetch count過大致使內存溢出問題
prefetch count太小致使吞吐量太低
這些底層機制和問題,我們都一步步分析清楚了。
因此到如今,單論消費端這塊的數據不丟失技術方案,相信你們在面試的時候就能夠有一整套本身的理解和方案能夠闡述了。
接下來下篇文章開始,咱們就來具體聊一聊:消息中間件的生產端如何保證數據不丟失。
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… 來源:掘金 著做權歸做者全部,轉載請聯繫做者得到受權!