高并发架构系列:MQ消息队列的12点核心原理总结
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
消息隊(duì)列已經(jīng)逐漸成為分布式應(yīng)用場(chǎng)景、內(nèi)部通信、以及秒殺等高并發(fā)業(yè)務(wù)場(chǎng)景的核心手段,它具有低耦合、可靠投遞、廣播、流量控制、最終一致性 等一系列功能。
無(wú)論是 RabbitMQ、RocketMQ、ActiveMQ、Kafka還是其它等,都有的一些基本原理、術(shù)語(yǔ)、機(jī)制等,總結(jié)分享出來(lái),希望大家在使用消息隊(duì)列技術(shù)的時(shí)候能夠快速理解。
1. 消息生產(chǎn)者、消息者、隊(duì)列
- 消息生產(chǎn)者Producer:發(fā)送消息到消息隊(duì)列。
- 消息消費(fèi)者Consumer:從消息隊(duì)列接收消息。
- Broker:概念來(lái)自與Apache ActiveMQ,指MQ的服務(wù)端,幫你把消息從發(fā)送端傳送到接收端。
- 消息隊(duì)列Queue:一個(gè)先進(jìn)先出的消息存儲(chǔ)區(qū)域。消息按照順序發(fā)送接收,一旦消息被消費(fèi)處理,該消息將從隊(duì)列中刪除。
2.設(shè)計(jì)Broker主要考慮
1)消息的轉(zhuǎn)儲(chǔ):在更合適的時(shí)間點(diǎn)投遞,或者通過一系列手段輔助消息最終能送達(dá)消費(fèi)機(jī)。
2)規(guī)范一種范式和通用的模式,以滿足解耦、最終一致性、錯(cuò)峰等需求。
3)其實(shí)簡(jiǎn)單理解就是一個(gè)消息轉(zhuǎn)發(fā)器,把一次RPC做成兩次RPC。發(fā)送者把消息投遞到broker,broker再將消息轉(zhuǎn)發(fā)一手到接收端。
總結(jié)起來(lái)就是兩次RPC加一次轉(zhuǎn)儲(chǔ),如果要做消費(fèi)確認(rèn),則是三次RPC。
3. 點(diǎn)對(duì)點(diǎn)消息隊(duì)列模型
點(diǎn)對(duì)點(diǎn)模型 用于 消息生產(chǎn)者 和 消息消費(fèi)者 之間 點(diǎn)到點(diǎn) 的通信。
點(diǎn)對(duì)點(diǎn)模式包含三個(gè)角色:
- 消息隊(duì)列(Queue)
- 發(fā)送者(Sender)
- 接收者(Receiver)
每個(gè)消息都被發(fā)送到一個(gè)特定的隊(duì)列,接收者從隊(duì)列中獲取消息。隊(duì)列保留著消息,可以放在 內(nèi)存 中也可以 持久化,直到他們被消費(fèi)或超時(shí)。
特點(diǎn)
- 每個(gè)消息只有一個(gè)消費(fèi)者(Consumer)(即一旦被消費(fèi),消息就不再在消息隊(duì)列中)
- 發(fā)送者和接收者之間在時(shí)間上沒有依賴性
- 接收者在成功接收消息之后需向隊(duì)列應(yīng)答成功
4. 發(fā)布訂閱消息模型Topic
發(fā)布訂閱模型包含三個(gè)角色:
- 主題(Topic)
- 發(fā)布者(Publisher)
- 訂閱者(Subscriber)
多個(gè)發(fā)布者將消息發(fā)送到Topic,系統(tǒng)將這些消息傳遞給多個(gè)訂閱者。
特點(diǎn)
- 每個(gè)消息可以有多個(gè)消費(fèi)者:和點(diǎn)對(duì)點(diǎn)方式不同,發(fā)布消息可以被所有訂閱者消費(fèi)
- 發(fā)布者和訂閱者之間有時(shí)間上的依賴性。
- 針對(duì)某個(gè)主題(Topic)的訂閱者,它必須創(chuàng)建一個(gè)訂閱者之后,才能消費(fèi)發(fā)布者的消息。
- 為了消費(fèi)消息,訂閱者必須保持運(yùn)行的狀態(tài)。
5.點(diǎn)對(duì)點(diǎn)和發(fā)布訂閱的區(qū)別
生產(chǎn)者發(fā)送一條消息到隊(duì)列queue,只有一個(gè)消費(fèi)者能收到。
發(fā)布者發(fā)送到topic的消息,只有訂閱了topic的訂閱者才會(huì)收到消息。
6. 消息的順序性保證
基于Queue消息模型,利用FIFO先進(jìn)先出的特性,可以保證消息的順序性。
7. 消息的ACK機(jī)制
即消息的Ackownledge確認(rèn)機(jī)制,
為了保證消息不丟失,消息隊(duì)列提供了消息Acknowledge機(jī)制,即ACK機(jī)制,當(dāng)Consumer確認(rèn)消息已經(jīng)被消費(fèi)處理,發(fā)送一個(gè)ACK給消息隊(duì)列,此時(shí)消息隊(duì)列便可以刪除這個(gè)消
息了。如果Consumer宕機(jī)/關(guān)閉,沒有發(fā)送ACK,消息隊(duì)列將認(rèn)為這個(gè)消息沒有被處理,會(huì)將這個(gè)消息重新發(fā)送給其他的Consumer重新消費(fèi)處理。
8.最終一致性的設(shè)計(jì)思路
主要是用“記錄”和“補(bǔ)償”的方式。
本地事務(wù)維護(hù)業(yè)務(wù)變化和通知消息,一起落地,然后RPC到達(dá)broker,在broker成功落地后,RPC返回成功,本地消息可以刪除。否則本地消息一直靠定時(shí)任務(wù)輪詢不斷重發(fā),這樣就保證了消息可靠落地broker。
broker往consumer發(fā)送消息的過程類似,一直發(fā)送消息,直到consumer發(fā)送消費(fèi)成功確認(rèn)。
我們先不理會(huì)重復(fù)消息的問題,通過兩次消息落地加補(bǔ)償,下游是一定可以收到消息的。然后依賴狀態(tài)機(jī)版本號(hào)等方式做判重,更新自己的業(yè)務(wù),就實(shí)現(xiàn)了最終一致性。
如果出現(xiàn)消費(fèi)方處理過慢消費(fèi)不過來(lái),要允許消費(fèi)方主動(dòng)ack error,并可以與broker約定下次投遞的時(shí)間。
對(duì)于broker投遞到consumer的消息,由于不確定丟失是在業(yè)務(wù)處理過程中還是消息發(fā)送丟失的情況下,有必要記錄下投遞的IP地址。決定重發(fā)之前詢問這個(gè)IP,消息處理成功了嗎?如果詢問無(wú)果,再重發(fā)。
事務(wù):本地事務(wù),本地落地,補(bǔ)償發(fā)送。本地事務(wù)做的,是業(yè)務(wù)落地和消息落地的事務(wù),而不是業(yè)務(wù)落地和RPC成功的事務(wù)。消息只要成功落地,很大程度上就沒有丟失的風(fēng)險(xiǎn)。
9. 消息的事務(wù)支持
消息的收發(fā)處理支持事務(wù),例如:在任務(wù)中心場(chǎng)景中,一次處理可能涉及多個(gè)消息的接收、處理,這應(yīng)該處于同一個(gè)事務(wù)范圍內(nèi),如果一個(gè)消息處理失敗,事務(wù)回滾,消息重新回到隊(duì)列中。
10. 消息的持久化
消息的持久化,對(duì)于一些關(guān)鍵的核心業(yè)務(wù)來(lái)說(shuō)是非常重要的,啟用消息持久化后,消息隊(duì)列宕機(jī)重啟后,消息可以從持久化存儲(chǔ)恢復(fù),消息不丟失,可以繼續(xù)消費(fèi)處理。
11. 消息隊(duì)列的高可用性
在實(shí)際生產(chǎn)環(huán)境中,使用單個(gè)實(shí)例的消息隊(duì)列服務(wù),如果遇到宕機(jī)、重啟等系統(tǒng)問題,消息隊(duì)列就無(wú)法提供服務(wù)了,因此很多場(chǎng)景下,我們希望消息隊(duì)列有高可用性支持,例如
RabbitMQ的鏡像集群模式的高可用性方案,ActiveMQ也有基于LevelDB+ZooKeeper的高可用性方案,以及Kafka的Replication機(jī)制等。
12.消息隊(duì)列的選型和應(yīng)用場(chǎng)景
具體請(qǐng)參考:高并發(fā)架構(gòu)系列:詳解分布式之消息隊(duì)列的特點(diǎn)、選型、及應(yīng)用場(chǎng)景。
?
以上是就是消息隊(duì)列MQ技術(shù)的一些梳理和歸納,希望對(duì)大家有幫助。
?
覺得不錯(cuò)請(qǐng)點(diǎn)贊支持,歡迎留言或進(jìn)我的個(gè)人群179961551領(lǐng)取【架構(gòu)資料專題目合集90期】、【BATJTMD大廠JAVA面試真題1000+】,本群專用于學(xué)習(xí)交流技術(shù)、分享面試機(jī)會(huì),拒絕廣告,我也會(huì)在群內(nèi)不定期答題、探討。
?
?
轉(zhuǎn)載于:https://my.oschina.net/jiagouzhan/blog/2994803
總結(jié)
以上是生活随笔為你收集整理的高并发架构系列:MQ消息队列的12点核心原理总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 星号*使用方法
- 下一篇: Golang基础之数组