為什么使用消息隊(duì)列

解耦

看這么個(gè)場景。A 系統(tǒng)發(fā)送數(shù)據(jù)到 BCD 三個(gè)系統(tǒng),通過接口調(diào)用發(fā)送。如果 E 系統(tǒng)也要這個(gè)數(shù)據(jù)呢?那如果 C 系統(tǒng)現(xiàn)在不需要了呢?A 系統(tǒng)負(fù)責(zé)人幾乎崩潰......

image.png

在這個(gè)場景中,A 系統(tǒng)跟其它各種亂七八糟的系統(tǒng)嚴(yán)重耦合,A 系統(tǒng)產(chǎn)生一條比較關(guān)鍵的數(shù)據(jù),很多系統(tǒng)都需要 A 系統(tǒng)將這個(gè)數(shù)據(jù)發(fā)送過來。A 系統(tǒng)要時(shí)時(shí)刻刻考慮 BCDE 四個(gè)系統(tǒng)如果掛了該咋辦?要不要重發(fā),要不要把消息存起來?頭發(fā)都白了??!

如果使用 MQ,A 系統(tǒng)產(chǎn)生一條數(shù)據(jù),發(fā)送到 MQ 里面去,哪個(gè)系統(tǒng)需要數(shù)據(jù)自己去 MQ 里面消費(fèi)。如果新系統(tǒng)需要數(shù)據(jù),直接從 MQ 里消費(fèi)即可;如果某個(gè)系統(tǒng)不需要這條數(shù)據(jù)了,就取消對 MQ 消息的消費(fèi)即可。這樣下來,A 系統(tǒng)壓根兒不需要去考慮要給誰發(fā)送數(shù)據(jù),不需要維護(hù)這個(gè)代碼,也不需要考慮人家是否調(diào)用成功、失敗超時(shí)等情況。

image.png

總結(jié):通過一個(gè) MQ,Pub/Sub 發(fā)布訂閱消息這么一個(gè)模型,A 系統(tǒng)就跟其它系統(tǒng)徹底解耦了。

面試技巧:你需要去考慮一下你負(fù)責(zé)的系統(tǒng)中是否有類似的場景,就是一個(gè)系統(tǒng)或者一個(gè)模塊,調(diào)用了多個(gè)系統(tǒng)或者模塊,互相之間的調(diào)用很復(fù)雜,維護(hù)起來很麻煩。但是其實(shí)這個(gè)調(diào)用是不需要直接同步調(diào)用接口的,如果用 MQ 給它異步化解耦,也是可以的,你就需要去考慮在你的項(xiàng)目里,是不是可以運(yùn)用這個(gè) MQ 去進(jìn)行系統(tǒng)的解耦。在簡歷中體現(xiàn)出來這塊東西,用 MQ 作解耦。

image.png

再來看一個(gè)場景,A 系統(tǒng)接收一個(gè)請求,需要在自己本地寫庫,還需要在 BCD 三個(gè)系統(tǒng)寫庫,自己本地寫庫要 3ms,BCD 三個(gè)系統(tǒng)分別寫庫要 300ms、450ms、200ms。最終請求總延時(shí)是 3 + 300 + 450 + 200 = 953ms,接近 1s,用戶感覺搞個(gè)什么東西,慢死了慢死了。用戶通過瀏覽器發(fā)起請求,等待個(gè) 1s,這幾乎是不可接受的。

image.png

一般互聯(lián)網(wǎng)類的企業(yè),對于用戶直接的操作,一般要求是每個(gè)請求都必須在 200 ms 以內(nèi)完成,對用戶幾乎是無感知的。

如果使用 MQ,那么 A 系統(tǒng)連續(xù)發(fā)送 3 條消息到 MQ 隊(duì)列中,假如耗時(shí) 5ms,A 系統(tǒng)從接受一個(gè)請求到返回響應(yīng)給用戶,總時(shí)長是 3 + 5 = 8ms,對于用戶而言,其實(shí)感覺上就是點(diǎn)個(gè)按鈕,8ms 以后就直接返回了,爽!網(wǎng)站做得真好,真快!

image.png

削峰

每天 0:00 到 12:00,A 系統(tǒng)風(fēng)平浪靜,每秒并發(fā)請求數(shù)量就 50 個(gè)。結(jié)果每次一到 12:00 ~ 13:00 ,每秒并發(fā)請求數(shù)量突然會(huì)暴增到 5k+ 條。但是系統(tǒng)是直接基于 MySQL的,大量的請求涌入 MySQL,每秒鐘對 MySQL 執(zhí)行約 5k 條 SQL。

一般的 MySQL,扛到每秒 2k 個(gè)請求就差不多了,如果每秒請求到 5k 的話,可能就直接把 MySQL 給打死了,導(dǎo)致系統(tǒng)崩潰,用戶也就沒法再使用系統(tǒng)了。

但是高峰期一過,到了下午的時(shí)候,就成了低峰期,可能也就 1w 的用戶同時(shí)在網(wǎng)站上操作,每秒中的請求數(shù)量可能也就 50 個(gè)請求,對整個(gè)系統(tǒng)幾乎沒有任何的壓力。

[圖片上傳失敗...(image-30f012-1543979244454)]

如果使用 MQ,每秒 5k 個(gè)請求寫入 MQ,A 系統(tǒng)每秒鐘最多處理 2k 個(gè)請求,因?yàn)?MySQL 每秒鐘最多處理 2k 個(gè)。A 系統(tǒng)從 MQ 中慢慢拉取請求,每秒鐘就拉取 2k 個(gè)請求,不要超過自己每秒能處理的最大請求數(shù)量就 ok,這樣下來,哪怕是高峰期的時(shí)候,A 系統(tǒng)也絕對不會(huì)掛掉。而 MQ 每秒鐘 5k 個(gè)請求進(jìn)來,就 2k 個(gè)請求出去,結(jié)果就導(dǎo)致在中午高峰期(1 個(gè)小時(shí)),可能有幾十萬甚至幾百萬的請求積壓在 MQ 中。

[圖片上傳失敗...(image-196bfe-1543979244454)]

這個(gè)短暫的高峰期積壓是 ok 的,因?yàn)楦叻迤谶^了之后,每秒鐘就 50 個(gè)請求進(jìn) MQ,但是 A 系統(tǒng)依然會(huì)按照每秒 2k 個(gè)請求的速度在處理。所以說,只要高峰期一過,A 系統(tǒng)就會(huì)快速將積壓的消息給解決掉。

消息隊(duì)列有什么優(yōu)缺點(diǎn)

優(yōu)點(diǎn)上面已經(jīng)說了,就是在特殊場景下有其對應(yīng)的好處,解耦、異步削峰。

缺點(diǎn)有以下幾個(gè):

  • 系統(tǒng)可用性降低
    系統(tǒng)引入的外部依賴越多,越容易掛掉。本來你就是 A 系統(tǒng)調(diào)用 BCD 三個(gè)系統(tǒng)的接口就好了,人 ABCD 四個(gè)系統(tǒng)好好的,沒啥問題,你偏加個(gè) MQ 進(jìn)來,萬一 MQ 掛了咋整,MQ 一掛,整套系統(tǒng)崩潰的,你不就完了?如何保證消息隊(duì)列的高可用,可以點(diǎn)擊這里查看。

  • 系統(tǒng)復(fù)雜度提高
    硬生生加個(gè) MQ 進(jìn)來,你怎么保證消息沒有重復(fù)消費(fèi)?怎么處理消息丟失的情況?怎么保證消息傳遞的順序性?頭大頭大,問題一大堆,痛苦不已。

  • 一致性問題
    A 系統(tǒng)處理完了直接返回成功了,人都以為你這個(gè)請求就成功了;但是問題是,要是 BCD 三個(gè)系統(tǒng)那里,BD 兩個(gè)系統(tǒng)寫庫成功了,結(jié)果 C 系統(tǒng)寫庫失敗了,咋整?你這數(shù)據(jù)就不一致了。

所以消息隊(duì)列實(shí)際是一種非常復(fù)雜的架構(gòu),你引入它有很多好處,但是也得針對它帶來的壞處做各種額外的技術(shù)方案和架構(gòu)來規(guī)避掉,做好之后,你會(huì)發(fā)現(xiàn),媽呀,系統(tǒng)復(fù)雜度提升了一個(gè)數(shù)量級,也許是復(fù)雜了 10 倍。但是關(guān)鍵時(shí)刻,用,還是得用的。

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么優(yōu)缺點(diǎn)?

特性 ActiveMQ RabbitMQ RocketMQ Kafka
單機(jī)吞吐量 萬級,比 RocketMQ、Kafka 低一個(gè)數(shù)量級 同 ActiveMQ 10 萬級,支撐高吞吐 10 萬級,高吞吐,一般配合大數(shù)據(jù)類的系統(tǒng)來進(jìn)行實(shí)時(shí)數(shù)據(jù)計(jì)算、日志采集等場景
topic 數(shù)量對吞吐量的影響 topic 可以達(dá)到幾百/幾千的級別,吞吐量會(huì)有較小幅度的下降,這是 RocketMQ 的一大優(yōu)勢,在同等機(jī)器下,可以支撐大量的 topic topic 從幾十到幾百個(gè)時(shí)候,吞吐量會(huì)大幅度下降,在同等機(jī)器下,Kafka 盡量保證 topic 數(shù)量不要過多,如果要支撐大規(guī)模的 topic,需要增加更多的機(jī)器資源
時(shí)效性 ms 級 微秒級,這是 RabbitMQ 的一大特點(diǎn),延遲最低 ms 級 延遲在 ms 級以內(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)過參數(shù)優(yōu)化配置,可以做到 0 丟失 同 RocketMQ
功能支持 MQ 領(lǐng)域的功能極其完備 基于 erlang 開發(fā),并發(fā)能力很強(qiáng),性能極好,延時(shí)很低 MQ 功能較為完善,還是分布式的,擴(kuò)展性好 功能較為簡單,主要支持簡單的 MQ 功能,在大數(shù)據(jù)領(lǐng)域的實(shí)時(shí)計(jì)算以及日志采集被大規(guī)模使用

綜上,各種對比之后,有如下建議:

一般的業(yè)務(wù)系統(tǒng)要引入 MQ,最早大家都用 ActiveMQ,但是現(xiàn)在確實(shí)大家用的不多了,沒經(jīng)過大規(guī)模吞吐量場景的驗(yàn)證,社區(qū)也不是很活躍,所以大家還是算了吧,我個(gè)人不推薦用這個(gè)了;

后來大家開始用 RabbitMQ,但是確實(shí) erlang 語言阻止了大量的 Java 工程師去深入研究和掌控它,對公司而言,幾乎處于不可控的狀態(tài),但是確實(shí)人家是開源的,比較穩(wěn)定的支持,活躍度也高;

不過現(xiàn)在確實(shí)越來越多的公司,會(huì)去用 RocketMQ,確實(shí)很不錯(cuò)(阿里出品),但社區(qū)可能有突然黃掉的風(fēng)險(xiǎn),對自己公司技術(shù)實(shí)力有絕對自信的,推薦用 RocketMQ,否則回去老老實(shí)實(shí)用 RabbitMQ 吧,人家有活躍的開源社區(qū),絕對不會(huì)黃。

所以中小型公司,技術(shù)實(shí)力較為一般,技術(shù)挑戰(zhàn)不是特別高,用 RabbitMQ 是不錯(cuò)的選擇;大型公司,基礎(chǔ)架構(gòu)研發(fā)實(shí)力較強(qiáng),用 RocketMQ 是很好的選擇。

如果是大數(shù)據(jù)領(lǐng)域的實(shí)時(shí)計(jì)算、日志采集等場景,用 Kafka 是業(yè)內(nèi)標(biāo)準(zhǔn)的,絕對沒問題,社區(qū)活躍度很高,絕對不會(huì)黃,何況幾乎是全世界這個(gè)領(lǐng)域的事實(shí)性規(guī)范。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一:為什么使用消息隊(duì)列 1,異步處理。程序中的非依賴關(guān)系的功能,如日志的收集,直接將需要處理的日志,丟到消息隊(duì)列中...
    時(shí)之令閱讀 698評論 0 0
  • 轉(zhuǎn)自:http://www.cnblogs.com/linjiqin/p/5720865.html一、消息隊(duì)列概述...
    striveSmile閱讀 883評論 0 49
  • 本來準(zhǔn)備等孩子放學(xué)回家,好好檢查一下她的作業(yè),結(jié)果吃了晚飯又臨時(shí)有事去忙了一會(huì),八點(diǎn)半了,回家一看孩子已經(jīng)睡著...
    孔家二小姐閱讀 319評論 0 0
  • 雜記一: EXCEL畫圖畫了一天,效率極其低下。畫圖以前熟練一點(diǎn)了,使用少了就還給誰了。 反思:1.做得少; 2....
    紫藤蘿哈哈哈閱讀 204評論 0 0
  • 最近經(jīng)常聽到大家買黑豆說補(bǔ)腎什么什么的,實(shí)在聽不下去了在這里講一下。黑豆形狀像腎,中醫(yī)講以類取象,又因?yàn)樯谒匀?..
    右邊的雨閱讀 905評論 0 1

友情鏈接更多精彩內(nèi)容