MQ的消息模型及在工作上應用場景
MQ介紹
根據某科的介紹,MQ(message queue),叫消息隊列,是基礎數據結構中先進先出的一種數據機構。
一般用來解決應用解耦,異步消息,流量削鋒等問題,實現高性能,高可用,可伸縮和最終一致性架構。
名詞 | 解釋 |
---|---|
解耦 | 簡單說就是積木化,每個東西都相互獨立,比如漢堡包,面包跟肉餅是相互獨立,可以單獨使用,也可以組合成一個食物 |
異步 | 去買漢堡包,下單之後就去玩手機,等服務員叫號通知領取,這就叫異步;而同步是下單後,什麼都不能幹,直到服務員叫號才能做其他事 |
限流 | 大傢 9 點上班,地鐵進不去,門口做限流 |
削峰 | 遵從最後落地到數據庫的請求數要盡量少的原則,比如讓 1/2 的人下午開始上班、局部停電,感興趣可以查看削峰填谷 |
消息 | 要傳輸的內容,比如說話、寫信,形式不重要,按照雙方約定的格式即可 |
隊列 | 是一種先進先出的數據結構,排隊打疫苗,從隊尾入隊,從隊頭出隊 |
MQ 主要產品包括:RabbitMQ、ActiveMQ、RocketMQ、ZeroMQ、Kafka
通過上述的內容,不難發現,MQ是一種跨進程的通信機制,用於上下遊傳遞消息,而個人覺得MQ有點像中介, 房東發佈出租信息,信息放在中介處,租客來通過中介來租房子。
使用 MQ 的好處
舉個通俗點的例子:
面試官希望 HR 早點招聘到合適的人選,於是一開始是這樣的:
HR 問面試官什麼時候有空,把候選人資料送過去,並且親自看到面試官看完並給出結論後才離開,時間一長,大傢都覺得很麻煩,HR 覺得候選人不錯,面試官覺得不合適,容易發生爭執。
後面,HR 跟面試官說,我把資料放在桌子上,你有空記得看,然後每次面試官看到桌子有資料後,都會拿起來看。
在這個場景上,HR就是生產者,面試官就是消費者,桌子就是MQ。
使用MQ帶來的好處是解決應用解耦,異步消息,流量削鋒:
- HR想給資料時,無需知道面試官是否有空,隻需要把資料放桌子上即可,這樣大傢都有時間做別的事,節省大傢的時間。。應用解耦,每個成員都是獨立的,不受其他成員影響。面試官不關心誰放的資料,HR 不關心誰哪個面試官看的資料
- 如果別的組也有招聘需求(且當是同一工種,比如 Java 後端開發),HR依然把資料放在桌子上,兩個面試官隻需要各自從桌子上取資料查閱即可。異步消息,HR 把資料放在桌子上即可,就可以去做別的事,比一開始親自看著的效率高太多瞭
- HR無需關註面試官什麼時候查看資料,也不關註看資料用多長的時間,減少矛盾。流量削峰,HR 給資料的頻率不固定,面試官看資料的時長也不固定,面試官隻需要在固定時間內看完給結論即可,不會有那麼大的壓力。
使用 MQ 的壞處
名詞 | 解釋 |
---|---|
引入復雜度 | 「桌子」這東西是使用 MQ 後多出來的,需要有地方放桌子,而且流程會變長,更復雜 |
不一致性 | HR會以為面試官應該看瞭資料,但實際面試官可能還沒開始看,這就導致瞭不一致性的問題,但在約束好的時間內,面試官最終的查閱狀態與HR的認知必須是要一致的,這就是所謂的最終不一致性 |
系統可用性降低 | 如果桌子壞瞭,後面的流程是不是就中斷瞭 |
當然,使用MQ
還有很多問題要解決,比如資料無辜丟瞭、一樣的資料,給瞭好多份、資料被搶、本來資料給面試官 A,結果給到面試官 B等場景都是需要處理的。
什麼時候用 MQ
名詞 | 解釋 |
---|---|
生產者不需要從消費者處獲得反饋 | 面試官到底看瞭沒有,HR 根本不需關註,默認面試官是看瞭,否則就隻能采取監督看完的方式 |
容許不一致性 | HR 可能會發現有時候面試官說看瞭資料,但實際沒看的情況,隻有 HR 願意相信面試官最後看瞭即可 |
有效 | 解耦、提速等帶來的收益大於放置書桌是有成本的,那說明是有效的。比如一個月甚至半年才有一份簡歷,那還不如直接當面給更高效 |
消息模型
什麼是 JMS
Java 消息服務指的是兩個應用程序之間進行異步通信的 API,它為標準消息協議和消息服務提供瞭一組通用接口,包括創建、發送、讀取消息等,用於支持 JAVA 應用程序開發。
為什麼需要 JMS
在JAVA
中,如果兩個應用程序之間對各自都不瞭解,甚至這兩個程序可能部署在不同地方上,那麼它們之間如何發送消息呢?
舉個例子,一個應用程序 A 部署在印度,另一個應用程序部署在美國,然後每當 A 觸發某件事後,B 想從 A 獲取一些更新信息。
當然,也有可能不止一個 B 對 A 的更新信息感興趣,可能會有 N 個類似 B 的應用程序想從 A 中獲取更新的信息。
在這種情況下,JAVA
提供瞭最佳的解決方案-JMS
,完美解決瞭上面討論的問題。
點對點模型
在該模型中,有下列概念:
消息隊列 (Queue)、發送者 (Sender)、接收者 (Receiver)
每個消息都被發送到一個特定的隊列,接收者從隊列中獲取消息。隊列保留著消息,直到它們被消費或超時。
- 支持存在多個消費者
- 每個消息隻有一個消費者(一旦消息被消費,消息就不再在消息隊列中)
- 發送者和接收者之間在時間上沒有依賴性,也就是說當發送者發送瞭消息之後,不管接收者有沒有正在運行,它不會影響到消息被發送到隊列
- 接收者在成功接收消息之後需向隊列應答成功
如果希望發送的每個消息都應該被成功處理的話,那麼就需要點對點模型。
女神想找備胎 A 聊天,就單聊備 A,這就是點對點,隻有一個人能收到消息
發佈訂閱模型
消息生產者(發佈)將消息發佈到topic
中,同時有多個消息消費者(訂閱)消費該消息。和點對點方式不同,發佈到 topic 的消息會被所有訂閱者消費。。
在該模型中,有下列概念:
主題(Topic)、發佈者(Publisher)、訂閱者(Subscriber)
客戶端將消息發送到主題。多個發佈者將消息發送到 Topic,系統將這些消息傳遞給多個訂閱者。
- 每個消息可以有多個消費者
- 發佈者和訂閱者有時間依賴性,隻有當客戶端創建訂閱後才能接受消息,且訂閱者需一直保持活動狀態以接收消息
- 訂閱者創建一個可持久化的訂閱。這樣,即使訂閱者沒有被激活(運行),它也能接收到發佈者的消息。
如果希望發送的消息可以不被做任何處理、或者被一個消費者處理、或者可以被多個消費者處理的話,那麼可以采用 Pub/Sub 模型。。
女神發瞭個朋友圈,她的備胎們都能看到,這就是發佈/訂閱。
兩個模型之間的區別
點對點模型下,不可重復消費。
點對點下,一個隊列可以有多個消費者,生產者發送一條消息到隊列,消費者能用隊列取出並且消費消息,一旦消息被消費後,隊列不再有存儲,所以其他消費者不能消費到已經被消費的消息,如果一直沒有消費者處理,這條消息就會被保存,直到有可用的消費者為止。
發佈訂閱模型,可以重復消費。
發佈訂閱下,發佈者發送到 topic 的消息,隻有訂閱瞭 topic 的訂閱者才會收到消息,註意是所有訂閱這個 topic 的服務都能收到,所以能達到消息拷貝的效果
MQ 的在工作上應用場景
雖然上面以一個招聘的例子來講解 MQ 的應用場景,但可能還是會有疑問,不知道工作上是如何的,因此再講講工作上的場景。
異步
之前負責的一個需求叫老帶新,大致流程如下:
1)用戶下單後,會先判斷下單者身份
2)如果是新用戶,再判斷是否有邀請人
3)如果有,再判斷邀請人身份
4)如果是老用戶,就給雙方發積分
這樣的話,用戶的流程就會發生變化:
很明顯,這樣做的問題是:新增的邏輯存在堵塞下單主流程的風險。
既然同步處理會有問題,那就改異步吧,改完變成這樣:
異步的好處是,即使老帶新邏輯有問題,也不會堵塞下單流程。
這樣的好日子沒過幾天,問題又來瞭:老帶新業務頻繁改動,導致下單系統頻繁發版本,存在質量隱患。
使用 MQ
由於依賴訂單系統的業務越來越多,為瞭保證下單系統的穩定性,業務層面必須解耦,隻需要把支付成功的消息告訴別的業務,他們收到瞭通知後自行處理,我們隻管自己的流程,後續還有其他業務系統,直接訂閱我們發送的支付成功消息。
「MQ 帶來的問題」
- 如何保證消息隊列的高可用?
- 如何保證消息不被重復消費?
- 如何處理消息丟失的問題?
- 如何保證消息的順序性?
- 如何處理消息隊列大量消息積壓?
上面這些問題,都是實際工作上會遇到的,往往也都是測試點,下面也會有提及到,簡單瞭解下即可。
「MQ 產品的對比」
產品 | 單機吞吐量 | 時效性 | 可用性 | 消息可靠性 | 功能支持 |
---|---|---|---|---|---|
ActiveMQ | 萬級 | 毫秒級 | 高 | 較低概率出現丟失數據 | 極其完備 |
RabbitMQ | 萬級 | 微妙級 | 高 | 基本不丟 | erlang 開發 |
RocketMQ | 十萬級 | 毫秒級 | 非常高 | 可配置 0 丟失 | 分佈式 |
Kafka | 十萬級 | 毫秒級 | 非常高高 | 可配置 0 丟失 | 分佈式 |
而在選擇上,一般公司都是用Kafka
跟RocketMQ
較多。
「MQ 的測試點」
生產者
- 生成的數據格式是否跟定義的一致
- 數據是否有成功推送到隊列裡
- 數據是否有成功推動到對應的 topic
- 推送失敗時如何處理
- 重復推送同一條數據,如何處理
- 不同順序推送消息,註意隊列優先級
- 推消息耗時
- 隊列容量達到上限,無法推送後如何處理
消費者
- 消費的消息是否來自訂閱的 topic
- 消息被消費瞭,是否有清除
- 生產者推送過快,消費速度過慢(堵塞),會如何
- 無法消費沒訂閱的 topic 消息
- 生產者推送消息後,消費者接受到的消息內容跟生產者推的一致
- 如何處理重復消息,比如冪等
- 處理超時
- 消息處理失敗
- 消費消息的優先級是否跟推的一致
- 消費消息耗時
- 消費者宕機,消息堆積,無人處理,會如何處理
- 是否能正常消費消息
隊列
- 宕機恢復後,消息是否丟失
- 宕機預案,多久能恢復,如果無法恢復的預案
- 不同的消息格式,是否能正常識別及轉發
小結
來來去去,花瞭一周的時間來整理這堆信息,之前有測過mq,但沒有太瞭解這玩意,從介紹、選型、測試點,加深瞭對 mq 的印象,但由於沒做過 mq 的性能測試跟自動化測試,所以這塊暫時沒有心得能輸出,如果後續有類似的經歷,也會分享下。
本文留下瞭一個懸念,針對消息不一致的問題,大傢是怎麼解決的,這邊非常好奇,所以下篇計劃會寫分佈式事務,想深入瞭解下細節~更多關於MQ工作場景消息模型的資料請關註WalkonNet其它相關文章!