最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

使用MQ的時候,怎么確保消息100%不丟失?

2023-01-27 17:08 作者:要寵你上天  | 我要投稿

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

這個問題在實際工作中很常見,既能考察候選者對于 MQ 中間件技術的掌握程度,又能很好地區(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ù)下游的處理能力自動調節(jié)流量。

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

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

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

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

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

  • 如何知道有消息丟失?

  • 哪些環(huán)節(jié)可能丟消息?

  • 如何確保消息不丟失?

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

案例解答

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

圖片

  • 消息生產階段:從消息被生產出來,然后提交給 MQ 的過程中,只要能正常收到 MQ Broker 的 ack 確認響應,就表示發(fā)送成功,所以只要處理好返回值和異常,這個階段是不會出現(xiàn)消息丟失的。

  • 消息存儲階段:這個階段一般會直接交給 MQ 消息中間件來保證,但是你要了解它的原理,比如 Broker 會做副本,保證一條消息至少同步兩個節(jié)點再返回 ack。

  • 消息消費階段:消費端從 Broker 上拉取消息,只要消費端在收到消息后,不立即發(fā)送消費確認給 Broker,而是等到執(zhí)行完業(yè)務邏輯后,再發(fā)送消費確認,也能保證消息的不丟失。

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

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

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

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

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

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

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

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

我們還是來看扣減京豆的例子,將賬戶 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 生成的技術方案。這也是面試官喜歡考察的問題,你也要掌握。

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

圖片

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

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

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

因為消息發(fā)送之后才會出現(xià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ū)來提高消費者的處理能力。

總結

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

  • 如何確保消息不會丟失?你要知道一條消息從發(fā)送到消費的每個階段,是否存在丟消息,以及如何監(jiān)控消息是否丟失,最后才是如何解決問題,方案可以基于“ MQ 的可靠消息投遞 ”的方式。

  • 如何保證消息不被重復消費?在進行消息補償?shù)臅r候,一定會存在重復消息的情況,那么如何實現(xiàn)消費端的冪等性就這道題的考點。

  • 如何處理消息積壓問題?這道題的考點就是如何通過 MQ 實現(xiàn)真正的高性能,回答的思路是,本著解決線上異常為最高優(yōu)先級,然后通過監(jiān)控和日志進行排查并優(yōu)化業(yè)務邏輯,最后是擴容消費端和分片的數(shù)量。

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

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

  • 如何選擇消息中間件?

  • 消息中間件中的隊列模型與發(fā)布訂閱模型的區(qū)別?

  • 為什么消息隊列能實現(xiàn)高吞吐?

  • 序列化、傳輸協(xié)議,以及內存管理等問題

  • … >


使用MQ的時候,怎么確保消息100%不丟失?的評論 (共 條)

分享到微博請遵守國家法律
开化县| 五大连池市| 息烽县| 江阴市| 东台市| 将乐县| 靖宇县| 河西区| 泸西县| 佛冈县| 平凉市| 陆良县| 蓬莱市| 阿尔山市| 张掖市| 获嘉县| 隆安县| 宜宾市| 泉州市| 寻甸| 禹州市| 兰考县| 武陟县| 蒙山县| 濮阳县| 德庆县| 合山市| 潢川县| 芦溪县| 嘉义县| 虹口区| 浦县| 珠海市| 霍邱县| 赫章县| 冀州市| 奇台县| 静乐县| 海宁市| 中方县| 介休市|