首先整理這個文章是因為我正好有機會實戰(zhàn)了一下rocketmq园担,阿里巴巴的一個開源消息中間件个初。所以就與以往中rabbitmq進行小小的比較一下。這里主線的根據(jù)常見面試問題進行整理歧譬。
一.消息隊列常用的場景
1.削峰
例如我們做得考試系統(tǒng)中宜猜,用戶通過人臉識別登錄系統(tǒng),考慮到考試系統(tǒng)的特殊性们镜,三萬名考生參加考試币叹,需要記錄人臉識別登錄照片。從考試完結(jié)果上看模狭,用戶最大并發(fā)數(shù)在4000颈抚,于是我們采用rocketMq來進行異步消費用戶人臉識別圖片,當時統(tǒng)計rocketMq每秒1000消費消息嚼鹉。及時反饋了考生人臉識別登錄成功贩汉,對數(shù)據(jù)庫寫操作也起到很大的緩沖功能。
2.解耦
如常用ABCD系統(tǒng)中锚赤,BCD系統(tǒng)都需要從A系統(tǒng)中調(diào)用接口返回數(shù)據(jù)匹舞,這時候突然來了E系統(tǒng),也需要A系統(tǒng)數(shù)线脚,又或者C系統(tǒng)不想要用這個接口數(shù)據(jù)了赐稽,而且A系統(tǒng)還得考慮,如果BCD接收不到數(shù)據(jù)浑侥,接收失敗咋整之類的問題姊舵。
如果基于消息隊列,這些問題就迎刃而解了寓落。
A系統(tǒng)直接把數(shù)據(jù)扔到Mq中括丁,BCDE系統(tǒng)直接從Mq中消費,如果消費失敗零如,則重試消費躏将。
3.異步
? ?比如下訂單系統(tǒng)中锄弱,會調(diào)用庫存系統(tǒng),會調(diào)用倉庫系統(tǒng)祸憋,積分系統(tǒng)等会宪,用戶訂單操作會直接返回給用戶信息,提示訂單完成蚯窥,至于庫存減少掸鹅,或者倉庫發(fā)貨又或者積分的增加等,都是異步完成拦赠。極大的提高用戶響應(yīng)速度巍沙。
二.各種消息隊列優(yōu)缺點
1.rabbitMq
? ? ? ? rabbitMq 幾萬級數(shù)據(jù)量,基于erlang語言開發(fā)荷鼠,因此響應(yīng)速度快些句携,并且社區(qū)活躍度比較活躍,可視化界面允乐。缺點就是數(shù)據(jù)吞吐量相對與小一些矮嫉,并且是基于erlang語言開發(fā),比較重的問題難以維護牍疏。
? ? 2.rocketMq
? ? ? ? rocketMq幾十萬級別數(shù)據(jù)量蠢笋,基于Java開發(fā),應(yīng)對了淘寶雙十一考驗鳞陨,并且文檔十分的完善昨寞,擁有一些其他消息隊列不具備的高級特性,如定時推送厦滤,其他消息隊列是延遲推送援岩,如rabbitMq通過設(shè)置expire字段設(shè)置延遲推送時間。又比如rocketmq實現(xiàn)分布式事務(wù)馁害,比較可靠的窄俏。
? ?3.kafka
? ? ? kafka真正的大規(guī)模分布式消息隊列,提供的核心功能比較少碘菜“简冢基于zookeeper實現(xiàn)的分布式消息訂閱。
三.消息隊列常使用的注意事項或者面試時候經(jīng)常問道的功能點
? ? 1.如何保證系統(tǒng)的高可用
? ? ? 就rabbitMq而言忍啸,有鏡像模式概念仰坦,就是用戶在發(fā)送數(shù)據(jù)時候,發(fā)送到mq機器上计雌,并且持久化磁盤悄晃,然后通過設(shè)置鏡像的queue,把數(shù)的持久化地址對應(yīng)表同步到另外mq機器上。這種就有效防止一臺mq掛了以后妈橄,另外的mq可以直接對外提供消費功能庶近。
? ? ? 就rocketMq而言,分為多主集群結(jié)構(gòu)眷蚓,多主多備異步復(fù)制結(jié)構(gòu)鼻种,多主多備同步復(fù)制結(jié)構(gòu)。
? ? 2.如何保證消息不會丟失
就rabbitmq而言沙热,從生產(chǎn)者叉钥,消費者,消息隊列角度分析篙贸。生產(chǎn)者而言投队,發(fā)送消息如果失敗,則定義重試次數(shù)爵川,一般設(shè)置成五次敷鸦。兩種解決方式1.通過設(shè)置事務(wù),進行事務(wù)回滾重試寝贡。2.通過發(fā)送者確認模式開啟轧膘。
方式一:channel.waitForConfirms()普通發(fā)送方確認模式;
方式二:channel.waitForConfirmsOrDie()批量確認模式兔甘;
方式三:channel.addConfirmListener()異步監(jiān)聽發(fā)送方確認模式;
就mq本身而言鳞滨,需要做隊列的持久化到磁盤的操作洞焙。1.queque隊列的持久化,通過channel.queue_declare(queue='hello', durable=True);設(shè)置
2.設(shè)置消息的持久化拯啦,通過delivery_mode=2來進行設(shè)置澡匪。
mq消費者而言,開啟手動ACK模式褒链,也就是需要真正的消費者入庫成功唁情,才會進行消費成功的確認。
總結(jié)就是一句話:發(fā)送者確認模式開啟甫匹,消息持久化默認開啟甸鸟,消費者消費開啟手動ack
rocketMq而言,生產(chǎn)者發(fā)送消息兵迅,生產(chǎn)者默認模式
rocketMq持久化方式中抢韭,消息持久化通過如下配置。
3.消費者冪等消費問題
感覺rabbitmq和rocketmq出現(xiàn)重復(fù)消費場景差不多
發(fā)送時消息重復(fù)
當一條消息已被成功發(fā)送到服務(wù)端并完成持久化恍箭,此時出現(xiàn)了網(wǎng)絡(luò)閃斷或者客戶端宕機刻恭,導(dǎo)致服務(wù)端對客戶端應(yīng)答失敗。 如果此時生產(chǎn)者意識到消息發(fā)送失敗并嘗試再次發(fā)送消息扯夭,消費者后續(xù)會收到兩條內(nèi)容相同并且 Message ID 也相同的消息鳍贾。
投遞時消息重復(fù)
消息消費的場景下鞍匾,消息已投遞到消費者并完成業(yè)務(wù)處理,當客戶端給服務(wù)端反饋應(yīng)答的時候網(wǎng)絡(luò)閃斷骑科。 為了保證消息至少被消費一次橡淑,消息隊列 RocketMQ 的服務(wù)端將在網(wǎng)絡(luò)恢復(fù)后再次嘗試投遞之前已被處理過的消息,消費者后續(xù)會收到兩條內(nèi)容相同并且 Message ID 也相同的消息纵散。
負載均衡時消息重復(fù)(包括但不限于網(wǎng)絡(luò)抖動梳码、Broker 重啟以及訂閱方應(yīng)用重啟)
當消息隊列 RocketMQ 的 Broker 或客戶端重啟、擴容或縮容時伍掀,會觸發(fā) Rebalance掰茶,此時消費者可能會收到重復(fù)消息。
? ? ? ?解決方式的話蜜笤,通過messageId濒蒋,作為數(shù)據(jù)庫業(yè)務(wù)主鍵,重復(fù)插入會報錯主鍵沖突問題把兔。
或者通過redis唯一性沪伙,messageId作為key存入,去重重復(fù)的數(shù)據(jù)县好,在從redis中刷到數(shù)據(jù)庫里面围橡。