<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:MQ 消息丟失、重復、積壓問題,如何解決?

          共 4466字,需瀏覽 9分鐘

           ·

          2022-08-25 10:00

          點擊關注公眾號,Java干貨及時送達??

          來源:blog.csdn.net/gu131007416553/article/details/120934738

          • 案例背景
          • 案例分析
          • 案例解答
          • 總結(jié)

          大家好,我是程序汪,MQ是面試中比較高頻的問題,下面分享下MQ的常見問題

          面試官在面試候選人時,如果發(fā)現(xiàn)候選人的簡歷中寫了在項目中使用了 MQ 技術(shù)(如 Kafka、RabbitMQ、RocketMQ),基本都會拋出一個問題:在使用 MQ 的時候,怎么確保消息 100% 不丟失?

          這個問題在實際工作中很常見,既能考察候選者對于 MQ 中間件技術(shù)的掌握程度,又能很好地區(qū)分候選人的能力水平。接下來,我們就從這個問題出發(fā),探討你應該掌握的基礎知識和答題思路,以及延伸的面試考點。

          案例背景

          以京東系統(tǒng)為例,用戶在購買商品時,通常會選擇用京豆抵扣一部分的金額,在這個過程中,交易服務和京豆服務通過 MQ 消息隊列進行通信。在下單時,交易服務發(fā)送“扣減賬戶 X 100 個京豆”的消息給 MQ 消息隊列,而京豆服務則在消費端消費這條命令,實現(xiàn)真正的扣減操作。

          圖片

          那在這個過程中你會遇到什么問題呢?

          案例分析

          要知道,在互聯(lián)網(wǎng)面試中,引入 MQ 消息中間件最直接的目的是:做系統(tǒng)解耦合流量控制,追其根源還是為了解決互聯(lián)網(wǎng)系統(tǒng)的高可用和高性能問題。

          • 系統(tǒng)解耦:用 MQ 消息隊列,可以隔離系統(tǒng)上下游環(huán)境變化帶來的不穩(wěn)定因素,比如京豆服務的系統(tǒng)需求無論如何變化,交易服務不用做任何改變,即使當京豆服務出現(xiàn)故障,主交易流程也可以將京豆服務降級,實現(xiàn)交易服務和京豆服務的解耦,做到了系統(tǒng)的高可用。
          • 流量控制:遇到秒殺等流量突增的場景,通過 MQ 還可以實現(xiàn)流量的“削峰填谷”的作用,可以根據(jù)下游的處理能力自動調(diào)節(jié)流量。

          不過引入 MQ 雖然實現(xiàn)了系統(tǒng)解耦合流量控制,也會帶來其他問題。

          引入 MQ 消息中間件實現(xiàn)系統(tǒng)解耦,會影響系統(tǒng)之間數(shù)據(jù)傳輸?shù)囊恢滦浴?/strong> 在分布式系統(tǒng)中,如果兩個節(jié)點之間存在數(shù)據(jù)同步,就會帶來數(shù)據(jù)一致性的問題。同理,在這一講你要解決的就是:消息生產(chǎn)端和消息消費端的消息數(shù)據(jù)一致性問題(也就是如何確保消息不丟失)。

          而引入 MQ 消息中間件解決流量控制 , 會使消費端處理能力不足從而導致消息積壓,這也是你要解決的問題。

          所以你能發(fā)現(xiàn),問題與問題之間往往是環(huán)環(huán)相扣的,面試官會借機考察你解決問題思路的連貫性和知識體系的掌握程度。

          那面對“在使用 MQ 消息隊列時,如何確保消息不丟失”這個問題時,你要怎么回答呢?首先,你要分析其中有幾個考點,比如:

          • 如何知道有消息丟失?
          • 哪些環(huán)節(jié)可能丟消息?
          • 如何確保消息不丟失?

          候選人在回答時,要先讓面試官知道你的分析思路,然后再提供解決方案 :網(wǎng)絡中的數(shù)據(jù)傳輸不可靠,想要解決如何不丟消息的問題,首先要知道哪些環(huán)節(jié)可能丟消息,以及我們?nèi)绾沃老⑹欠駚G失了,最后才是解決方案(而不是上來就直接說自己的解決方案)。就好比“架構(gòu)設計”“架構(gòu)”體現(xiàn)了架構(gòu)師的思考過程,而“設計”才是最后的解決方案,兩者缺一不可。

          案例解答

          我們首先來看消息丟失的環(huán)節(jié),一條消息從生產(chǎn)到消費完成這個過程,可以劃分三個階段,分別為消息生產(chǎn)階段,消息存儲階段和消息消費階段。

          圖片
          • 消息生產(chǎn)階段: 從消息被生產(chǎn)出來,然后提交給 MQ 的過程中,只要能正常收到 MQ Broker 的 ack 確認響應,就表示發(fā)送成功,所以只要處理好返回值和異常,這個階段是不會出現(xiàn)消息丟失的。
          • 消息存儲階段: 這個階段一般會直接交給 MQ 消息中間件來保證,但是你要了解它的原理,比如 Broker 會做副本,保證一條消息至少同步兩個節(jié)點再返回 ack。
          • 消息消費階段: 消費端從 Broker 上拉取消息,只要消費端在收到消息后,不立即發(fā)送消費確認給 Broker,而是等到執(zhí)行完業(yè)務邏輯后,再發(fā)送消費確認,也能保證消息的不丟失。

          方案看似萬無一失,每個階段都能保證消息的不丟失,但在分布式系統(tǒng)中,故障不可避免,作為消息生產(chǎn)端,你并不能保證 MQ 是不是弄丟了你的消息,消費者是否消費了你的消息,所以,本著 Design for Failure 的設計原則,你還是需要一種機制,來 Check 消息是否丟失了。

          緊接著,你還可以向面試官闡述怎么進行消息檢測? 總體方案解決思路為:在消息生產(chǎn)端,給每個發(fā)出的消息都指定一個全局唯一 ID,或者附加一個連續(xù)遞增的版本號,然后在消費端做對應的版本校驗。

          具體怎么落地實現(xiàn)呢?你可以利用攔截器機制。 在生產(chǎn)端發(fā)送消息之前,通過攔截器將消息版本號注入消息中(版本號可以采用連續(xù)遞增的 ID 生成,也可以通過分布式全局唯一 ID生成)。然后在消費端收到消息后,再通過攔截器檢測版本號的連續(xù)性或消費狀態(tài),這樣實現(xiàn)的好處是消息檢測的代碼不會侵入到業(yè)務代碼中,可以通過單獨的任務來定位丟失的消息,做進一步的排查。

          這里需要你注意:如果同時存在多個消息生產(chǎn)端和消息消費端,通過版本號遞增的方式就很難實現(xiàn)了,因為不能保證版本號的唯一性,此時只能通過全局唯一 ID 的方案來進行消息檢測,具體的實現(xiàn)原理和版本號遞增的方式一致。

          現(xiàn)在,你已經(jīng)知道了哪些環(huán)節(jié)(消息存儲階段、消息消費階段)可能會出問題,并有了如何檢測消息丟失的方案,然后就要給出解決防止消息丟失的設計方案。

          回答完“如何確保消息不會丟失?” 之后,面試官通常會追問“怎么解決消息被重復消費的問題?

          比如:在消息消費的過程中,如果出現(xiàn)失敗的情況,通過補償?shù)臋C制發(fā)送方會執(zhí)行重試,重試的過程就有可能產(chǎn)生重復的消息,那么如何解決這個問題?

          這個問題其實可以換一種說法,就是如何解決消費端冪等性問題(冪等性,就是一條命令,任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同),只要消費端具備了冪等性,那么重復消費消息的問題也就解決了。Java項目分享  最新整理全集

          我們還是來看扣減京豆的例子,將賬戶 X 的金豆個數(shù)扣減 100 個,在這個例子中,我們可以通過改造業(yè)務邏輯,讓它具備冪等性。

          圖片

          最簡單的實現(xiàn)方案,就是在數(shù)據(jù)庫中建一張消息日志表 , 這個表有兩個字段:消息 ID 和消息執(zhí)行狀態(tài)。這樣,我們消費消息的邏輯可以變?yōu)椋涸谙⑷罩颈碇性黾右粭l消息記錄,然后再根據(jù)消息記錄,異步操作更新用戶京豆余額。

          因為我們每次都會在插入之前檢查是否消息已存在,所以就不會出現(xiàn)一條消息被執(zhí)行多次的情況,這樣就實現(xiàn)了一個冪等的操作。當然,基于這個思路,不僅可以使用關系型數(shù)據(jù)庫,也可以通過 Redis 來代替數(shù)據(jù)庫實現(xiàn)唯一約束的方案。

          在這里我多說一句,想要解決“消息丟失”和“消息重復消費”的問題,有一個前提條件就是要實現(xiàn)一個全局唯一 ID 生成的技術(shù)方案。這也是面試官喜歡考察的問題,你也要掌握。

          在分布式系統(tǒng)中,全局唯一 ID 生成的實現(xiàn)方法有數(shù)據(jù)庫自增主鍵、UUID、Redis,Twitter-Snowflake 算法,我總結(jié)了幾種方案的特點,你可以參考下。

          圖片

          我提醒你注意,無論哪種方法,如果你想同時滿足簡單、高可用和高性能,就要有取舍,所以你要站在實際的業(yè)務中,說明你的選型所考慮的平衡點是什么。我個人在業(yè)務中比較傾向于選擇 Snowflake 算法,在項目中也進行了一定的改造,主要是讓算法中的 ID 生成規(guī)則更加符合業(yè)務特點,以及優(yōu)化諸如時鐘回撥等問題。

          當然,除了“怎么解決消息被重復消費的問題?”之外,面試官還會問到你“消息積壓”。 原因在于消息積壓反映的是性能問題,解決消息積壓問題,可以說明候選者有能力處理高并發(fā)場景下的消費能力問題。

          你在解答這個問題時,依舊要傳遞給面試官一個這樣的思考過程: 如果出現(xiàn)積壓,那一定是性能問題,想要解決消息從生產(chǎn)到消費上的性能問題,就首先要知道哪些環(huán)節(jié)可能出現(xiàn)消息積壓,然后在考慮如何解決。

          因為消息發(fā)送之后才會出現(xiàn)積壓的問題,所以和消息生產(chǎn)端沒有關系,又因為絕大部分的消息隊列單節(jié)點都能達到每秒鐘幾萬的處理能力,相對于業(yè)務邏輯來說,性能不會出現(xiàn)在中間件的消息存儲上面。毫無疑問,出問題的肯定是消息消費階段,那么從消費端入手,如何回答呢?

          如果是線上突發(fā)問題,要臨時擴容,增加消費端的數(shù)量,與此同時,降級一些非核心的業(yè)務。通過擴容和降級承擔流量,這是為了表明你對應急問題的處理能力。

          其次,才是排查解決異常問題,如通過監(jiān)控,日志等手段分析是否消費端的業(yè)務邏輯代碼出現(xiàn)了問題,優(yōu)化消費端的業(yè)務處理邏輯。

          最后,如果是消費端的處理能力不足,可以通過水平擴容來提供消費端的并發(fā)處理能力,但這里有一個考點需要特別注意 , 那就是在擴容消費者的實例數(shù)的同時,必須同步擴容主題 Topic 的分區(qū)數(shù)量,確保消費者的實例數(shù)和分區(qū)數(shù)相等。如果消費者的實例數(shù)超過了分區(qū)數(shù),由于分區(qū)是單線程消費,所以這樣的擴容就沒有效果。

          比如在 Kafka 中,一個 Topic 可以配置多個 Partition(分區(qū)),數(shù)據(jù)會被寫入到多個分區(qū)中,但在消費的時候,Kafka 約定一個分區(qū)只能被一個消費者消費,Topic 的分區(qū)數(shù)量決定了消費的能力,所以,可以通過增加分區(qū)來提高消費者的處理能力。Java項目分享 最新整理全集

          總結(jié)

          至此,我們講解了 MQ 消息隊列的熱門問題的解決方案,無論是初中級還是高級研發(fā)工程師,本篇文章的內(nèi)容都是你需要掌握的,你都可以從這幾點出發(fā),與面試官進行友好的交流。我來總結(jié)一下今天的重點內(nèi)容。

          • 如何確保消息不會丟失? 你要知道一條消息從發(fā)送到消費的每個階段,是否存在丟消息,以及如何監(jiān)控消息是否丟失,最后才是如何解決問題,方案可以基于“ MQ 的可靠消息投遞 ”的方式。
          • 如何保證消息不被重復消費? 在進行消息補償?shù)臅r候,一定會存在重復消息的情況,那么如何實現(xiàn)消費端的冪等性就這道題的考點。
          • 如何處理消息積壓問題? 這道題的考點就是如何通過 MQ 實現(xiàn)真正的高性能,回答的思路是,本著解決線上異常為最高優(yōu)先級,然后通過監(jiān)控和日志進行排查并優(yōu)化業(yè)務邏輯,最后是擴容消費端和分片的數(shù)量。

          在回答問題的時候,你需要特別注意的是,讓面試官了解到你的思維過程,這種解決問題的能力是面試官更為看中的,比你直接回答一道面試題更有價值。

          另外,如果你應聘的部門是基礎架構(gòu)部,那么除了要掌握本講中的常見問題的主線知識以外,還要掌握消息中間件的其他知識體系,如:

          • 如何選型消息中間件?
          • 消息中間件中的隊列模型與發(fā)布訂閱模型的區(qū)別?
          • 為什么消息隊列能實現(xiàn)高吞吐?
          • 序列化、傳輸協(xié)議,以及內(nèi)存管理等問題
          • … >


          程序汪資料鏈接

          程序汪接的7個私活都在這里,經(jīng)驗整理

          Java項目分享  最新整理全集,找項目不累啦 07版

          堪稱神級的Spring Boot手冊,從基礎入門到實戰(zhàn)進階

          臥槽!字節(jié)跳動《算法中文手冊》火了,完整版 PDF 開放下載!

          臥槽!阿里大佬總結(jié)的《圖解Java》火了,完整版PDF開放下載!

          字節(jié)跳動總結(jié)的設計模式 PDF 火了,完整版開放下載!

          歡迎添加程序汪個人微信 itwang009  進粉絲群或圍觀朋友圈

          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  学生妺毛片视频 | 免费的黄色A片 | 人人人人操人人人人精品 | 日日干免费视频 | 国模无码在线 |