面試官:消息隊(duì)列的應(yīng)用場(chǎng)景有哪些?
通常來(lái)說(shuō),使用消息隊(duì)列主要能為我們的系統(tǒng)帶來(lái)下面三點(diǎn)好處:
- 異步處理
- 削峰/限流
- 降低系統(tǒng)耦合性
除了這三點(diǎn)之外,消息隊(duì)列還有其他的一些應(yīng)用場(chǎng)景,例如實(shí)現(xiàn)分布式事務(wù)、順序保證和數(shù)據(jù)流處理。
如果在面試的時(shí)候你被面試官問(wèn)到這個(gè)問(wèn)題的話(huà),一般情況是你在你的簡(jiǎn)歷上涉及到消息隊(duì)列這方面的內(nèi)容,這個(gè)時(shí)候推薦你結(jié)合你自己的項(xiàng)目來(lái)回答。
異步處理
通過(guò)異步處理提高系統(tǒng)性能
將用戶(hù)請(qǐng)求中包含的耗時(shí)操作,通過(guò)消息隊(duì)列實(shí)現(xiàn)異步處理,將對(duì)應(yīng)的消息發(fā)送到消息隊(duì)列之后就立即返回結(jié)果,減少響應(yīng)時(shí)間,提高用戶(hù)體驗(yàn)。隨后,系統(tǒng)再對(duì)消息進(jìn)行消費(fèi)。
因?yàn)橛脩?hù)請(qǐng)求數(shù)據(jù)寫(xiě)入消息隊(duì)列之后就立即返回給用戶(hù)了,但是請(qǐng)求數(shù)據(jù)在后續(xù)的業(yè)務(wù)校驗(yàn)、寫(xiě)數(shù)據(jù)庫(kù)等操作中可能失敗。因此,使用消息隊(duì)列進(jìn)行異步處理之后,需要適當(dāng)修改業(yè)務(wù)流程進(jìn)行配合,比如用戶(hù)在提交訂單之后,訂單數(shù)據(jù)寫(xiě)入消息隊(duì)列,不能立即返回用戶(hù)訂單提交成功,需要在消息隊(duì)列的訂單消費(fèi)者進(jìn)程真正處理完該訂單之后,甚至出庫(kù)后,再通過(guò)電子郵件或短信通知用戶(hù)訂單成功,以免交易糾紛。這就類(lèi)似我們平時(shí)手機(jī)訂火車(chē)票和電影票。
削峰/限流
先將短時(shí)間高并發(fā)產(chǎn)生的事務(wù)消息存儲(chǔ)在消息隊(duì)列中,然后后端服務(wù)再慢慢根據(jù)自己的能力去消費(fèi)這些消息,這樣就避免直接把后端服務(wù)打垮掉。
舉例:在電子商務(wù)一些秒殺、促銷(xiāo)活動(dòng)中,合理使用消息隊(duì)列可以有效抵御促銷(xiāo)活動(dòng)剛開(kāi)始大量訂單涌入對(duì)系統(tǒng)的沖擊。如下圖所示:
削峰
降低系統(tǒng)耦合性
使用消息隊(duì)列還可以降低系統(tǒng)耦合性。我們知道如果模塊之間不存在直接調(diào)用,那么新增模塊或者修改模塊就對(duì)其他模塊影響較小,這樣系統(tǒng)的可擴(kuò)展性無(wú)疑更好一些。
生產(chǎn)者(客戶(hù)端)發(fā)送消息到消息隊(duì)列中去,消費(fèi)者(服務(wù)端)處理消息,需要消費(fèi)的系統(tǒng)直接去消息隊(duì)列取消息進(jìn)行消費(fèi)即可而不需要和其他系統(tǒng)有耦合,這顯然也提高了系統(tǒng)的擴(kuò)展性。
發(fā)布/訂閱(Pub/Sub)模型
消息隊(duì)列使用發(fā)布-訂閱模式工作,消息發(fā)送者(生產(chǎn)者)發(fā)布消息,一個(gè)或多個(gè)消息接受者(消費(fèi)者)訂閱消息。 從上圖可以看到消息發(fā)送者(生產(chǎn)者)和消息接受者(消費(fèi)者)之間沒(méi)有直接耦合,消息發(fā)送者將消息發(fā)送至分布式消息隊(duì)列即結(jié)束對(duì)消息的處理,消息接受者從分布式消息隊(duì)列獲取該消息后進(jìn)行后續(xù)處理,并不需要知道該消息從何而來(lái)。對(duì)新增業(yè)務(wù),只要對(duì)該類(lèi)消息感興趣,即可訂閱該消息,對(duì)原有系統(tǒng)和業(yè)務(wù)沒(méi)有任何影響,從而實(shí)現(xiàn)網(wǎng)站業(yè)務(wù)的可擴(kuò)展性設(shè)計(jì)。
例如,我們商城系統(tǒng)分為用戶(hù)、訂單、財(cái)務(wù)、倉(cāng)儲(chǔ)、消息通知、物流、風(fēng)控等多個(gè)服務(wù)。用戶(hù)在完成下單后,需要調(diào)用財(cái)務(wù)(扣款)、倉(cāng)儲(chǔ)(庫(kù)存管理)、物流(發(fā)貨)、消息通知(通知用戶(hù)發(fā)貨)、風(fēng)控(風(fēng)險(xiǎn)評(píng)估)等服務(wù)。使用消息隊(duì)列后,下單操作和后續(xù)的扣款、發(fā)貨、通知等操作就解耦了,下單完成發(fā)送一個(gè)消息到消息隊(duì)列,需要用到的地方去訂閱這個(gè)消息進(jìn)行消息即可。
圖片
另外,為了避免消息隊(duì)列服務(wù)器宕機(jī)造成消息丟失,會(huì)將成功發(fā)送到消息隊(duì)列的消息存儲(chǔ)在消息生產(chǎn)者服務(wù)器上,等消息真正被消費(fèi)者服務(wù)器處理后才刪除消息。在消息隊(duì)列服務(wù)器宕機(jī)后,生產(chǎn)者服務(wù)器會(huì)選擇分布式消息隊(duì)列服務(wù)器集群中的其他服務(wù)器發(fā)布消息。
備注: 不要認(rèn)為消息隊(duì)列只能利用發(fā)布-訂閱模式工作,只不過(guò)在解耦這個(gè)特定業(yè)務(wù)環(huán)境下是使用發(fā)布-訂閱模式的。除了發(fā)布-訂閱模式,還有點(diǎn)對(duì)點(diǎn)訂閱模式(一個(gè)消息只有一個(gè)消費(fèi)者),我們比較常用的是發(fā)布-訂閱模式。另外,這兩種消息模型是 JMS 提供的,AMQP 協(xié)議還提供了另外 5 種消息模型。
實(shí)現(xiàn)分布式事務(wù)
分布式事務(wù)的解決方案之一就是 MQ 事務(wù)。
RocketMQ、 Kafka、Pulsar、QMQ 都提供了事務(wù)相關(guān)的功能。事務(wù)允許事件流應(yīng)用將消費(fèi),處理,生產(chǎn)消息整個(gè)過(guò)程定義為一個(gè)原子操作。
RocketMQ 事務(wù)消息原理如下圖所示:
圖片
順序保證
在很多應(yīng)用場(chǎng)景中,處理數(shù)據(jù)的順序至關(guān)重要。消息隊(duì)列保證數(shù)據(jù)按照特定的順序被處理,適用于那些對(duì)數(shù)據(jù)順序有嚴(yán)格要求的場(chǎng)景。大部分消息隊(duì)列,例如 RocketMQ、RabbitMQ、Pulsar、Kafka,都支持順序消息。
延時(shí)/定時(shí)處理
消息發(fā)送后不會(huì)立即被消費(fèi),而是指定一個(gè)時(shí)間,到時(shí)間后再消費(fèi)。大部分消息隊(duì)列,例如 RocketMQ、RabbitMQ、Pulsar、Kafka,都支持定時(shí)/延時(shí)消息。
圖片
數(shù)據(jù)流處理
針對(duì)分布式系統(tǒng)產(chǎn)生的海量數(shù)據(jù)流,如業(yè)務(wù)日志、監(jiān)控?cái)?shù)據(jù)、用戶(hù)行為等,消息隊(duì)列可以實(shí)時(shí)或批量收集這些數(shù)據(jù),并將其導(dǎo)入到大數(shù)據(jù)處理引擎中,實(shí)現(xiàn)高效的數(shù)據(jù)流管理和處理。