MQ全程(Message Queue)又名消息隊列,是一種異步通訊的中間件。可以理解爲郵局,發送者將消息投遞到郵局,然後郵局幫我們發送給具體的接收者,具體發送過程和時間與我們無關。
消息隊列是分佈式系統中重要的組件,消息隊列主要解決了應用耦合、異步處理、流量削鋒等問題。
當前使用較多的消息隊列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等,而部分數據庫如Redis、Mysql以及phxsql也可實現消息隊列的功能。
消息隊列在實際應用中包括如下四個場景:
應用耦合:多應用間通過消息隊列對同一消息進行處理,避免調用接口失敗導致整個過程失敗;
異步處理:多應用對消息隊列中同一消息進行處理,應用間併發處理消息,相比串行處理,減少處理時間;
限流削峯:廣泛應用於秒殺或搶購活動中,避免流量過大導致應用系統掛掉的情況;
消息驅動的系統:系統分爲消息隊列、消息生產者、消息消費者,生產者負責產生消息,消費者(可能有多個)負責對消息進行處理;
下面詳細介紹上述四個場景以及消息隊列如何在上述四個場景中使用:
1、應用耦合
場景說明:用戶下單後,訂單系統需要通知庫存系統。傳統的做法是,訂單系統調用庫存系統的接口。如下圖
傳統模式的缺點:
假如庫存系統無法訪問,則訂單減庫存將失敗,從而導致訂單失敗
訂單系統與庫存系統耦合
訂單系統:用戶下單後,訂單系統完成持久化處理,將消息寫入消息隊列,返回用戶訂單下單成功
庫存系統:訂閱下單的消息,採用拉/推的方式,獲取下單信息,庫存系統根據下單信息,進行庫存操作
假如:在下單時庫存系統不能正常使用。也不影響正常下單,因爲下單後,訂單系統寫入消息隊列就不再關心其他的後續操作了。實現訂單系統與庫存系統的應用解耦
解耦是消息中間件的一個主要作用,標準的用法是:
生產者生產消息傳送到隊列,消費者從隊列中拿取消息並處理,生產者不用關心是誰來消費,消費者不用關心誰在生產消息,從而達到解耦的目的。
2、異步處理
具體場景:用戶爲了使用某個應用,進行註冊,系統需要發送註冊郵件並驗證短信。對這兩個操作的處理方式有兩種:串行及並行。
1)串行方式:將註冊信息寫入數據庫成功後,發送註冊郵件,再發送註冊短信。以上三個任務全部完成後,返回給客戶端
2)並行方式:將註冊信息寫入數據庫成功後,發送註冊郵件的同時,發送註冊短信。以上三個任務完成後,返回給客戶端。與串行的差別是,並行的方式可以提高處理的時間
引入消息隊列,將不是必須的業務邏輯,異步處理。改造後的架構如下
按照以上約定,用戶的響應時間相當於是註冊信息寫入數據庫的時間,也就是50毫秒。註冊郵件,發送短信寫入消息隊列後,直接返回,因此寫入消息隊列的速度很快,基本可以忽略,因此用戶的響應時間可能是50毫秒。因此架構改變後,系統的吞吐量提高到每秒20 QPS。比串行提高了3倍,比並行提高了兩倍
3、限流削峯
具體場景:購物網站開展秒殺活動,一般由於瞬時訪問量過大,服務器接收過大,會導致流量暴增,相關係統無法處理請求甚至崩潰。而加入消息隊列後,系統可以從消息隊列中取數據,相當於消息隊列做了一次緩衝。
可以控制活動的人數
可以緩解短時間內高流量壓垮應用
用戶的請求,服務器接收後,首先寫入消息隊列。假如消息隊列長度超過最大數量,則直接拋棄用戶請求或跳轉到錯誤頁面
秒殺業務根據消息隊列中的請求信息,再做後續處理
比方說一個秒殺需求,一用有1萬件商品,如果每筆秒殺訂單,都去訪問一次數據庫,查一查庫存,那得花費多長時間啊。
我們可以這樣做,用一個消息隊列,定製它的長度爲1萬,1萬以內可以存到消息隊列,並立馬反饋秒殺成功,之後再去做減庫存等一系列操作。一萬以後不再近消息隊列,並立馬反饋秒殺失敗。
4、消息驅動的系統
具體場景:用戶新上傳了一批照片, 人臉識別系統需要對這個用戶的所有照片進行聚類,聚類完成後由對賬系統重新生成用戶的人臉索引(加快查詢)。這三個子系統間由消息隊列連接起來,前一個階段的處理結果放入隊列中,後一個階段從隊列中獲取消息繼續處理。
該方法有如下優點:
避免了直接調用下一個系統導致當前系統失敗;
每個子系統對於消息的處理方式可以更爲靈活,可以選擇收到消息時就處理,可以選擇定時處理,也可以劃分時間段按不同處理速度處理;
消息隊列包括兩種模式,點對點模式(point to point, queue)和發佈/訂閱模式(publish/subscribe,topic)。
點對點式
生產者生產消息,存到消息隊列中去,消費者去消息隊列裏邊消費。消費者在成功接收消息之後需向隊列應答成功,以便消息隊列刪除當前消費的消息,從而保證不重複消費信息
點對點模式特點:
每個消息只有一個接收者(Consumer)(即一旦被消費,消息就不再在消息隊列中);
發送者和接收者間沒有依賴性,發送者發送消息之後,不管有沒有接收者在運行,都不會影響到發送者下次發送消息;
接收者在成功接收消息之後需向隊列應答成功,以便消息隊列刪除當前接收的消息;
發佈訂閱式:
發佈者將消息發送到Topic,系統將這些消息傳遞給多個訂閱者。
發佈/訂閱模式特點:
每個消息可以有多個訂閱者;
發佈者和訂閱者之間有時間上的依賴性。針對某個主題(Topic)的訂閱者,它必須創建一個訂閱者之後,才能消費發佈者的消息。
爲了消費消息,訂閱者需要提前訂閱該角色主題,並保持在線運行;
持久化消息比較—zeroMq不支持,activeMq和rabbitMq都支持。持久化消息主要是指:MQ down或者MQ所在的服務器down了,消息不會丟失的機制。
可靠性、靈活的路由、集羣、事務、高可用的隊列、消息排序、問題追蹤、可視化管理工具、插件系統、社區—RabbitMq最好,ActiveMq次之,ZeroMq最差。
高併發—從實現語言來看,RabbitMQ最高,原因是它的實現語言是天生具備高併發高可用的erlang語言。
綜上所述:RabbitMQ的性能相對來說更好更全面,是消息中間件的首選。