面試官:你的項目為什么要用消息隊列?

今天我們探討一種廣泛使用的中間件:消息隊列。
消息隊列由來已久,通常用于不同系統(tǒng)之間的通信。下圖以星巴克的工作方式為例,來說明消息隊列的概念。
在星巴克,收銀員接受訂單并收錢,然后把顧客的名字寫在咖啡杯上,交給下一個步驟。咖啡制作師拿起訂單和杯子制作咖啡。然后,顧客到柜臺領取咖啡。這三個步驟同步進行。收銀員只需將訂單以咖啡杯的形式放入,無需等待訂單完成。咖啡制作師只需將制作完成的咖啡放在柜臺上,就可以去制作下一杯咖啡了,無需等待顧客取走。
這個過程的美妙之處在于每個步驟都是獨立運行的,很像一個異步系統(tǒng)。
這種異步處理(每一步都無需等待前一步完成)大大提高了系統(tǒng)的吞吐量。例如,收銀員在接受另一份訂單之前,無需等待您的飲料制作完成。
01
一個秒殺的案例
我們來看一個真實系統(tǒng)的例子:電商中經(jīng)常出現(xiàn)的秒殺。由于秒殺期間用戶活躍度激增,會給系統(tǒng)帶來很大壓力。消息隊列通常在后端優(yōu)化中起著關鍵作用。
下圖列出了一個簡化的電子商務秒殺架構。這時我們還沒有對其進行優(yōu)化,只是簡單列出了數(shù)據(jù)流。
-
步驟 1 和 2:客戶向訂單服務下訂單。
-
步驟 3:在處理付款之前,訂單服務會鎖定該用戶占用的庫存。
-
步驟 4:訂單服務向支付服務發(fā)送支付指令。支付服務向 3 個服務發(fā)送消息:支付渠道、通知服務和數(shù)據(jù)分析。
-
步驟 5.1 和 6.1:支付服務向外部支付通道發(fā)送支付指令。支付通道與外部支付服務提供商(Payment Service Provider, PSP)對話,最終完成交易。
-
步驟 5.2 和 6.2:支付服務向通知服務發(fā)送消息,然后通知服務通過電子郵件或短信向客戶發(fā)送通知。
-
步驟 5.3:支付服務向數(shù)據(jù)分析服務發(fā)送交易詳情。
在秒殺期間,無縫的用戶體驗至關重要。為了在高流量情況下保持服務響應速度,可以在系統(tǒng)多個階段集成消息隊列,以確保最佳性能。
02
使用消息隊列優(yōu)化秒殺系統(tǒng)
我們下面一步一步地優(yōu)化這個秒殺系統(tǒng),來看看消息隊列給系統(tǒng)帶來了什么好處。
扇出
扇出(fan out)這個概念來源于電子電路,是指由一個邏輯門的輸出驅動幾個下游邏輯門的輸入,從而連接形成更復雜的電路。
支付服務將消息發(fā)送到三個下游服務,分別用于不同的目的:支付渠道、通知服務和數(shù)據(jù)分析。生產(chǎn)者(支付服務)只需將信息放到隊列中,不同的消費者就可以按照自己的節(jié)奏處理信息。這種扇出簡化了系統(tǒng)架構。
異步處理
以星巴克為例,正如收銀員不會等待咖啡煮好一樣,訂單服務也不會等待付款最終完成。支付指令被置于隊列中,一旦最終完成,客戶就會收到通知。
流控
在秒殺活動中,可能會有數(shù)以萬計的用戶同時下訂單。如何在滿足客戶需求和保持系統(tǒng)穩(wěn)定之間取得平衡至關重要。
一種常見的方法是在特定時間段內(nèi)對收到的請求數(shù)量設置上限,使其與系統(tǒng)容量相匹配。過多的請求可能會被拒絕或被要求在短暫延遲后重試。這種方法可確保系統(tǒng)保持穩(wěn)定,不會不堪重負。對于成功通過的請求,消息隊列可確保它們得到高效、有序的處理。如果系統(tǒng)的某個部分暫時滯后,訂單也不會丟失。它將被保留在隊列中,直到可以處理為止。
服務解耦
我們的設計在多處使用了消息隊列。服務之間使用定義明確的消息接口進行交互,而不是彼此緊密依賴。每個服務都可以獨立修改和部署。每個組件都可以用不同的編程語言開發(fā)。這為架構設計帶來了靈活性。
橫向可擴展性
由于服務是解耦的,因此我們可以根據(jù)業(yè)務需求對它們進行獨立擴展。每個服務都能以不同的容量提供服務,因此我們可以根據(jù)其計劃的 QPS(query per second)或 TPS(transaction per second)進行擴展。
消息持久性
消息隊列也可用作存儲消息的中間件。如果上游服務崩潰,下游服務總能從消息隊列中拾取消息進行處理。這樣,恢復功能就從每個服務中轉移出來,交由消息隊列負責。
批量處理
我們有時需要進行批量數(shù)據(jù)的處理。例如,當支付服務向數(shù)據(jù)分析服務發(fā)送消息時,數(shù)據(jù)分析服務并不需要執(zhí)行實時更新,而是設置一個滾動窗口來批量處理窗口內(nèi)的數(shù)據(jù)。批量處理是下游服務的要求,因此支付服務無需知道,只需將消息放入隊列即可。消息定序 秒殺活動的庫存商品數(shù)量是有限的。例如,秒殺只提供 10 部 iPhone,但下單的用戶超過 10,000 人。我們該如何決定訂單順序呢?用消息隊列來保存所有訂單會有一個自然的順序:隊列中的前 10 位將獲得 iPhone。
下圖中顯示了所有的優(yōu)化點。服務通過消息隊列連接并解耦。這樣,架構就能實現(xiàn)更高的吞吐量。
歷史好文:
