在使用 MQ 的時候,怎麼確保訊息 100% 不丟失?
阿新 • • 發佈:2022-03-17
這個問題在實際工作中很常見,既能考察候選者對於 MQ 中介軟體技術的掌握程度,又能很好地區分候選人的能力水平。接下來從這個問題出發,探討應該掌握的基礎知識和答題思路,以及延伸的面試考點。
案例背景
以京東系統為例,使用者在購買商品時,通常會選擇用京豆抵扣一部分的金額,在這個過程中,交易服務和京豆服務通過 MQ 訊息佇列進行通訊。在下單時,交易服務傳送“扣減賬戶 X 100 個京豆”的訊息給 MQ 訊息佇列,而京豆服務則在消費端消費這條命令,實現真正的扣減操作。
分析
引入 MQ 訊息中介軟體最直接的目的:做系統解耦合流量控制,解決網際網路系統的高可用和高效能問題。
- 系統解耦:用 MQ 訊息佇列,可以隔離系統上下游環境變化帶來的不穩定因素。
京豆服務的系統需求無論如何變化,交易服務不用做任何改變,即使當京豆服務出現故障,主交易流程也可以將京豆服務降級,實現交易服務和京豆服務的解耦,做到了系統的高可用。 - 流量控制:遇到秒殺等流量突增的場景,通過 MQ 還可以實現流量的“削峰填谷”的作用,可以根據下游的處理能力自動調節流量。
引入 MQ 也會帶來其他問題:
- 實現了系統解耦,會影響系統之間資料傳輸的一致性。
- 解決流量控制, 會使消費端處理能力不足從而導致訊息積壓。
解決方案
首先分析問題的幾個要點:
- 哪些環節可能丟訊息?
- 如何知道有訊息丟失?
- 如何確保訊息不丟失?
訊息丟失的環節
一條訊息從生產到消費完成這個過程,可以劃分三個階段:訊息生產階段,訊息儲存階段和訊息消費階段。
- 訊息生產階段:從訊息被生產出來,然後提交給 MQ 的過程中,只要能正常收到 MQ Broker 的 ack 確認響應,就表示傳送成功,所以只要處理好返回值和異常,這個階段是不會出現訊息丟失的。
- 訊息儲存階段:這個階段一般會直接交給 MQ 訊息中介軟體來保證,Broker 會做副本,保證一條訊息至少同步兩個節點再返回 ack。
- 訊息消費階段:消費端從 Broker 上拉取訊息,只要消費端在收到訊息後,不立即傳送消費確認給 Broker,而是等到執行完業務邏輯後,再發送消費確認,也能保證訊息的不丟失。
方案看似每個階段都能保證訊息的不丟失,但在分散式系統中,故障不可避免,作為訊息生產端並不能保證 MQ 是不是弄丟了訊息,所以還是需要一種機制來檢查訊息是否丟失了。
總體方案解決思路:在訊息生產端,給每個發出的訊息都指定一個全域性唯一 ID,或者附加一個連續遞增的版本號,然後在消費端做對應的版本校驗。