1. 面試官:MQ 消息丟失、重復(fù)、積壓問題,如何解決?

        共 4466字,需瀏覽 9分鐘

         ·

        2022-08-25 10:00

        點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)??

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

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

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

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

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

        案例背景

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

        圖片

        那在這個(gè)過程中你會(huì)遇到什么問題呢?

        案例分析

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

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

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

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

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

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

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

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

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

        案例解答

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

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

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

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

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

        這里需要你注意:如果同時(shí)存在多個(gè)消息生產(chǎn)端和消息消費(fèi)端,通過版本號(hào)遞增的方式就很難實(shí)現(xiàn)了,因?yàn)椴荒鼙WC版本號(hào)的唯一性,此時(shí)只能通過全局唯一 ID 的方案來進(jìn)行消息檢測(cè),具體的實(shí)現(xiàn)原理和版本號(hào)遞增的方式一致。

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

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

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

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

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

        圖片

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

        因?yàn)槲覀兠看味紩?huì)在插入之前檢查是否消息已存在,所以就不會(huì)出現(xiàn)一條消息被執(zhí)行多次的情況,這樣就實(shí)現(xiàn)了一個(gè)冪等的操作。當(dāng)然,基于這個(gè)思路,不僅可以使用關(guān)系型數(shù)據(jù)庫,也可以通過 Redis 來代替數(shù)據(jù)庫實(shí)現(xiàn)唯一約束的方案。

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

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

        圖片

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

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

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

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

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

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

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

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

        總結(jié)

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

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

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

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

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


        程序汪資料鏈接

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

        Java項(xiàng)目分享  最新整理全集,找項(xiàng)目不累啦 07版

        堪稱神級(jí)的Spring Boot手冊(cè),從基礎(chǔ)入門到實(shí)戰(zhàn)進(jìn)階

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

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

        字節(jié)跳動(dòng)總結(jié)的設(shè)計(jì)模式 PDF 火了,完整版開放下載!

        歡迎添加程序汪個(gè)人微信 itwang009  進(jìn)粉絲群或圍觀朋友圈

        瀏覽 38
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 国产高清不卡视频 | 有肏屄的视频吗 | 色婷婷五月天在线视频 | 亚洲视频完整版在线观看 | 一级黄片在线看 |