聊一聊系統(tǒng)設(shè)計(jì)中的消息隊(duì)列
在一個(gè)電商平臺(tái)系統(tǒng)里,每當(dāng)客戶(hù)下訂單時(shí),你需要:
- 處理支付。
- 更新庫(kù)存。
- 發(fā)送確認(rèn)郵件。
在高峰期立即執(zhí)行所有這些操作,可能會(huì)減慢客戶(hù)的體驗(yàn)。
在這種情況下,我們有大量的應(yīng)用事件,而無(wú)法同時(shí)處理所有事件。
消息隊(duì)列的基本架構(gòu)
消息隊(duì)列是一個(gè)持久化組件,存儲(chǔ)在內(nèi)存中,支持異步通信。它充當(dāng)緩沖區(qū),并分發(fā)異步請(qǐng)求。
消息隊(duì)列的基本架構(gòu)很簡(jiǎn)單。輸入服務(wù)稱(chēng)為生產(chǎn)者或發(fā)布者,創(chuàng)建并將消息發(fā)布到消息隊(duì)列。其他服務(wù)稱(chēng)為消費(fèi)者或訂閱者,連接到隊(duì)列并執(zhí)行消息定義的操作。
在實(shí)際場(chǎng)景中,可能有許多應(yīng)用程序?qū)懭腙?duì)列,也有許多服務(wù)器從隊(duì)列讀取。
回到例子
在我們的案例中,處理每個(gè)任務(wù)時(shí),可以將其添加到隊(duì)列的末尾,然后從這個(gè)隊(duì)列將它們發(fā)送到我們的服務(wù)器。
- 訂單已下: 訂單詳細(xì)信息放入一條消息中。
- 消息已發(fā)送: 消息被添加到隊(duì)列中。
- 工作程序處理: 獨(dú)立的進(jìn)程(工作程序)從隊(duì)列的前端提取消息并處理任務(wù)。
我們的服務(wù)器確認(rèn)已接收并處理一條消息,隊(duì)列則將其移除,以免第二次發(fā)送。
使用消息隊(duì)列的好處
主要優(yōu)點(diǎn)是我們解耦了這些事件,消息隊(duì)列允許我們異步處理這些事件。我們可以將它們排隊(duì),直到可以處理。
使用消息隊(duì)列時(shí),當(dāng)消費(fèi)者無(wú)法處理消息時(shí),生產(chǎn)者可以將消息發(fā)布到隊(duì)列中。
消費(fèi)者即使在生產(chǎn)者不可用時(shí)也可以從隊(duì)列中讀取消息。
另一個(gè)很大的好處是它們是持久化的。如果隊(duì)列崩潰,數(shù)據(jù)不會(huì)丟失,因?yàn)樗淮鎯?chǔ)在內(nèi)存中,而是存儲(chǔ)在磁盤(pán)上。
如果工作程序在處理消息時(shí)崩潰,也沒(méi)問(wèn)題!消息仍在隊(duì)列中,將被另一個(gè)工作程序提取。
消息隊(duì)列還提供了可擴(kuò)展性。如果接收到大量訂單,隊(duì)列會(huì)變得更長(zhǎng)。你可以添加更多的工作程序來(lái)處理額外的負(fù)載,而不影響網(wǎng)站。
不同的隊(duì)列類(lèi)型
消息隊(duì)列有多種類(lèi)型。最常見(jiàn)的包括:
- FIFO(先進(jìn)先出): 就像一個(gè)普通的隊(duì)列,消息按照到達(dá)的順序處理。這對(duì)于支付處理等情況非常重要。
- 優(yōu)先隊(duì)列: 某些消息可能比其他消息更重要。你可以?xún)?yōu)先處理這些消息。
推送與拉取
一些隊(duì)列等待工作程序請(qǐng)求消息(拉取式隊(duì)列),而另一些則主動(dòng)將消息發(fā)送給工作程序(推送式隊(duì)列)。
示例
以下是一些流行的消息隊(duì)列示例:
- RabbitMQ: 一種多用途隊(duì)列,適合多種用例。
- Kafka: 為高吞吐量和實(shí)時(shí)數(shù)據(jù)流設(shè)計(jì),適用于日志記錄和事件驅(qū)動(dòng)架構(gòu)。
- Amazon SQS(簡(jiǎn)單隊(duì)列服務(wù)): AWS提供的完全托管的基于云的隊(duì)列服務(wù)。它可擴(kuò)展且可靠,具有延遲隊(duì)列和死信隊(duì)列等功能。