面試必備:對(duì)消息隊(duì)列的理解?
簡(jiǎn)述:
消息隊(duì)列,MessageQueue,簡(jiǎn)稱MQ。消息隊(duì)列中間件是分布式系統(tǒng)中重要的組件。
消息(Message)是指在應(yīng)用之間傳送的數(shù)據(jù),消息可以非常簡(jiǎn)單,比如只包含文本字符串,也可以更復(fù)雜,可能包含嵌入對(duì)象。
消息隊(duì)列(Message Queue)是一種應(yīng)用間的通信方式,消息發(fā)送后可以立即返回,有消息系統(tǒng)來(lái)確保信息的可靠專遞,消息發(fā)布者只管把消息發(fā)布到MQ中而不管誰(shuí)來(lái)取,
消息使用者只管從MQ中取消息而不管誰(shuí)發(fā)布的,這樣發(fā)布者和使用者都不用知道對(duì)方的存在。
架構(gòu)模型:

Producer:消息生產(chǎn)者,負(fù)責(zé)產(chǎn)生和發(fā)送消息到 Broker;
Broker:消息處理中心。負(fù)責(zé)消息存儲(chǔ)、確認(rèn)、重試等,一般其中會(huì)包含多個(gè) queue;
Consumer:消息消費(fèi)者,負(fù)責(zé)從 Broker 中獲取消息,并進(jìn)行相應(yīng)處理;
詳解:
我們?cè)陂_發(fā)的過(guò)程中,會(huì)遇到像這樣的情況:
比如,我們需要開發(fā)一個(gè)給注冊(cè)用戶發(fā)送郵件的功能。其實(shí)制作起來(lái)并不是很難,無(wú)非就是兩步,
1、獲取需要發(fā)送郵件的郵箱,并填寫發(fā)送內(nèi)容。
2、發(fā)送。
這功能實(shí)現(xiàn)起來(lái)很簡(jiǎn)單,也很寫,對(duì)吧!
那么,現(xiàn)在問(wèn)題來(lái)了。
我現(xiàn)在有好百萬(wàn)的并發(fā),幾百萬(wàn)個(gè)用戶同時(shí)都在注冊(cè)(當(dāng)然這里是假設(shè))。這么高并發(fā)的情況下,我們還是用同步的方式去執(zhí)行上面的1和2這兩個(gè)步驟。
我可以很負(fù)責(zé)的告訴大家,一定會(huì)出現(xiàn)發(fā)送失敗的案例,而且會(huì)很多。
那怎么解決這樣的問(wèn)題呢?
消息隊(duì)列?。?!
這里我們就引入了消息隊(duì)列的概念。在理解這個(gè)概念之前,我們先來(lái)看一個(gè)生活中的小例子:
我們都到餐廳去吃過(guò)飯對(duì)吧,服務(wù)員點(diǎn)單和廚師做菜,一定是服務(wù)員點(diǎn)單遠(yuǎn)遠(yuǎn)快于廚師做菜。那么問(wèn)題再一次來(lái)了,如果服務(wù)員點(diǎn)單和廚師做菜是單線程的同步執(zhí)行的。
那么我們作為顧客,一定會(huì)有很大的怨言。因?yàn)槲覀円鹊缴弦蛔c(diǎn)單的是的菜上齊過(guò)后才能點(diǎn)餐。
但是在現(xiàn)實(shí)生活中,沒(méi)有一家餐廳是這樣的。通常餐廳中服務(wù)員點(diǎn)單和廚師做菜沒(méi)有直接聯(lián)系,服務(wù)員只管點(diǎn)單,點(diǎn)單成功后記錄在一個(gè)介質(zhì)上(這里假設(shè)為記錄在紙上),然后傳遞給后廚,后廚再按照單子的前后順序依次制作。
其實(shí),我們上面每天都經(jīng)歷的這個(gè)情形就是一個(gè)典型的消息隊(duì)列:消息發(fā)布者(服務(wù)員),將消息存入消息隊(duì)列(紙質(zhì)點(diǎn)單記錄),消息執(zhí)行者(廚師)從消息隊(duì)列取得消息并執(zhí)行。
看了上面的例子,我相信絕大部分人對(duì)消息隊(duì)列都應(yīng)該有了一定的認(rèn)識(shí)了。
下面為消息隊(duì)列的一個(gè)抽象圖。(生產(chǎn)者:服務(wù)員、消費(fèi)者:廚師)

下面,我們來(lái)講一下如何使用消息隊(duì)列實(shí)現(xiàn)百萬(wàn)并發(fā)的郵件發(fā)送(保證每一封郵件都能發(fā)送成功,除非客戶填寫了一個(gè)錯(cuò)誤的郵件地址,這里我們不考慮這種情況)
需要注意的是,存儲(chǔ)消息的介質(zhì)有很多,我們可以根據(jù)需求隨意選擇,不用拘泥于redis的list。這里我們暫且選擇mysql作為消息的存儲(chǔ)介質(zhì)。
我們新建一個(gè)表,用于存儲(chǔ)消息。表明為MQ,含有三個(gè)字段id、u_email(用戶郵箱)、post_content(發(fā)送內(nèi)容)。
1、當(dāng)用戶申請(qǐng)注冊(cè)的時(shí)候,將用戶的郵箱和發(fā)送內(nèi)容(發(fā)送內(nèi)容可以視情況而定,這里的邏輯就具體問(wèn)題具體分析了哈)存入MQ表,存入成功后馬上就可以給用戶反饋。比如(請(qǐng)到您的郵箱查看郵件是否已發(fā)送到您的郵箱......)
2、用php實(shí)現(xiàn)一個(gè)定時(shí)器,定時(shí)從MQ表中取出數(shù)據(jù),進(jìn)行郵件發(fā)送。如果成功則從數(shù)據(jù)表MQ中刪除該條記錄(當(dāng)然,一般我們用邏輯刪除),如果沒(méi)有成功,則不刪除。
優(yōu)點(diǎn):
1、后臺(tái)運(yùn)行,前臺(tái)無(wú)需等待,馬上可以給客戶以反應(yīng),友好度較高。
2、成功率高,失敗的記錄會(huì)自動(dòng)重發(fā),直到成功。
在工作中會(huì)遇到很多剛接觸消息隊(duì)列的程序員,誤以為redis的list就是消息隊(duì)列。其實(shí)list只是redis的一種數(shù)據(jù)類型,它能夠?qū)崿F(xiàn)消息隊(duì)列功能而已。
消息隊(duì)列中間件有那些?
有Kafka、ActiveMQ、RabbitMQ、RocketMQ ?
他們的優(yōu)缺點(diǎn):
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
|---|---|---|---|---|
| 單機(jī)吞吐量 | 萬(wàn)級(jí),比 RocketMQ、Kafka 低一個(gè)數(shù)量級(jí) | 同 ActiveMQ | 10 萬(wàn)級(jí),支撐高吞吐 | 10 萬(wàn)級(jí),高吞吐,一般配合大數(shù)據(jù)類的系統(tǒng)來(lái)進(jìn)行實(shí)時(shí)數(shù)據(jù)計(jì)算、日志采集等場(chǎng)景 |
| topic 數(shù)量對(duì)吞吐量的影響 | topic 可以達(dá)到幾百/幾千的級(jí)別,吞吐量會(huì)有較小幅度的下降,這是 RocketMQ 的一大優(yōu)勢(shì),在同等機(jī)器下,可以支撐大量的 topic | topic 從幾十到幾百個(gè)時(shí)候,吞吐量會(huì)大幅度下降,在同等機(jī)器下,Kafka 盡量保證 topic 數(shù)量不要過(guò)多,如果要支撐大規(guī)模的 topic,需要增加更多的機(jī)器資源 | ||
| 時(shí)效性 | ms 級(jí) | 微秒級(jí),這是 RabbitMQ 的一大特點(diǎn),延遲最低 | ms 級(jí) | 延遲在 ms 級(jí)以內(nèi) |
| 可用性 | 高,基于主從架構(gòu)實(shí)現(xiàn)高可用 | 同 ActiveMQ | 非常高,分布式架構(gòu) | 非常高,分布式,一個(gè)數(shù)據(jù)多個(gè)副本,少數(shù)機(jī)器宕機(jī),不會(huì)丟失數(shù)據(jù),不會(huì)導(dǎo)致不可用 |
| 消息可靠性 | 有較低的概率丟失數(shù)據(jù) | 基本不丟 | 經(jīng)過(guò)參數(shù)優(yōu)化配置,可以做到 0 丟失 | 同 RocketMQ |
| 功能支持 | MQ 領(lǐng)域的功能極其完備 | 基于 erlang 開發(fā),并發(fā)能力很強(qiáng),性能極好,延時(shí)很低 | MQ 功能較為完善,還是分布式的,擴(kuò)展性好 | 功能較為簡(jiǎn)單,主要支持簡(jiǎn)單的 MQ 功能,在大數(shù)據(jù)領(lǐng)域的實(shí)時(shí)計(jì)算以及日志采集被大規(guī)模使用 |
綜上,各種對(duì)比之后,有如下建議:
一般的業(yè)務(wù)系統(tǒng)要引入 MQ,最早大家都用 ActiveMQ,但是現(xiàn)在確實(shí)大家用的不多了,沒(méi)經(jīng)過(guò)大規(guī)模吞吐量場(chǎng)景的驗(yàn)證,社區(qū)也不是很活躍,所以大家還是算了吧,我個(gè)人不推薦用這個(gè)了;
后來(lái)大家開始用 RabbitMQ,但是確實(shí) erlang 語(yǔ)言阻止了大量的 Java 工程師去深入研究和掌控它,對(duì)公司而言,幾乎處于不可控的狀態(tài),但是確實(shí)人家是開源的,比較穩(wěn)定的支持,活躍度也高;
不過(guò)現(xiàn)在確實(shí)越來(lái)越多的公司,會(huì)去用 RocketMQ,確實(shí)很不錯(cuò)(阿里出品),但社區(qū)可能有突然黃掉的風(fēng)險(xiǎn),對(duì)自己公司技術(shù)實(shí)力有絕對(duì)自信的,推薦用 RocketMQ,否則回去老老實(shí)實(shí)用 RabbitMQ 吧,人家有活躍的開源社區(qū),絕對(duì)不會(huì)黃。
所以中小型公司,技術(shù)實(shí)力較為一般,技術(shù)挑戰(zhàn)不是特別高,用 RabbitMQ 是不錯(cuò)的選擇;大型公司,基礎(chǔ)架構(gòu)研發(fā)實(shí)力較強(qiáng),用 RocketMQ 是很好的選擇。如果是大數(shù)據(jù)領(lǐng)域的實(shí)時(shí)計(jì)算、日志采集等場(chǎng)景,用 Kafka 是業(yè)內(nèi)標(biāo)準(zhǔn)的,絕對(duì)沒(méi)問(wèn)題,社區(qū)活躍度很高,絕對(duì)不會(huì)黃,何況幾乎是全世界這個(gè)領(lǐng)域的事實(shí)性規(guī)范。
引用:https://www.cnblogs.com/wuzm/p/11105176.html
引用:https://www.cnblogs.com/573734817pc/p/10931632.html
支持小微:
騰訊云 搞活動(dòng)了?玩服務(wù)器的可以搞搞。就這幾天時(shí)間。
云服務(wù)器限時(shí)秒殺,1核2G 首年95元!
鏈接:https://curl.qcloud.com/RX2amrlR
右下角,您點(diǎn)一下在看圖片
小微工資漲1毛
商務(wù)合作QQ:185601686
