RabbitMQ順序性、可靠性、重復(fù)消費(fèi)、消息堆積解決方案-創(chuàng)新互聯(lián)

RabbitMQ順序性、可靠性(消息丟失)、重復(fù)消費(fèi)、消息堆積解決方案 順序性

RabbitMQ使用過(guò)程中,有些業(yè)務(wù)場(chǎng)景需要我們保證順序消費(fèi),例如:業(yè)務(wù)上產(chǎn)生三條消息,分別是對(duì)數(shù)據(jù)的增加、修改、刪除操作,如果沒(méi)有保證順序消費(fèi),執(zhí)行順序可能變成刪除、修改、增加,這就亂了 。
在這里插入圖片描述

成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站建設(shè)、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的保定網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

RabbitMQ的消息順序問(wèn)題,需要分三個(gè)環(huán)節(jié)看待,發(fā)送消息的順序、隊(duì)列中消息的順序、消費(fèi)消息的順序。

發(fā)送消息的順序

先看一下是什么原因造成了發(fā)送消息時(shí)候的順序錯(cuò)亂

  • 消息生產(chǎn)者啟用了發(fā)送確認(rèn)(ack)機(jī)制,在發(fā)生中斷時(shí),需要 RabbitMQ 補(bǔ)償發(fā)送時(shí),那么此時(shí)消息在源頭就已經(jīng)出現(xiàn)順序混亂了,導(dǎo)致消息被消費(fèi)時(shí)也是亂序的
  • 另一種情況,如果消息發(fā)送時(shí),設(shè)置了超時(shí)時(shí)間,并且采用了死信隊(duì)列,模擬了延時(shí)隊(duì)列的效果,那么此時(shí)消息的順序也時(shí)不能保證的
  • 還有一種情況,如果消息設(shè)置了優(yōu)先級(jí),那么在高并發(fā)的情況下,消息的順序也是得不到保證的,消息的消費(fèi)順序也就不能保證了

發(fā)送消息的順序性,一般來(lái)說(shuō)不做要求,但是如果一定要求順序,可以使用鎖機(jī)制配合 ack機(jī)制 來(lái)保證消息的順序到達(dá)

隊(duì)列中消息的順序

消息隊(duì)列中的消息是遵循FIFO(先進(jìn)先出)原則,天然有序

消費(fèi)消息的順序

有這樣一個(gè)訂單操作,insert 、update、delete連續(xù)操作,并且消息已經(jīng)順序存在queue中,那么如何保證消費(fèi)順序是insert 、update、delete,而不是delete、insert 、update呢?

方案一:拆分多個(gè)queue,每個(gè)queue一個(gè)consumer,該條訂單的相關(guān)操作全部放到這個(gè)queue中,由這一個(gè)consumer消費(fèi),這樣做多了一些queue。

方案二:就一個(gè)queue但是對(duì)應(yīng)一個(gè)consumer,然后這個(gè)consumer內(nèi)部用內(nèi)存隊(duì)列做排隊(duì),該條訂單相關(guān)的消息全部放到一個(gè)隊(duì)列中,然后分發(fā)給底層不同的worker線程來(lái)處理

可靠性

實(shí)際上消息隊(duì)列是沒(méi)法百分百保證不丟失的,我們只能盡量降低概率,然后在消息丟失后記錄日志,再處理

有這樣一個(gè)典型的訂單場(chǎng)景

在這里插入圖片描述

  • MQ 掛了,消息沒(méi)發(fā)出去。創(chuàng)建訂單后面幾個(gè)優(yōu)惠券、積分的下游系統(tǒng)全都沒(méi)有執(zhí)行業(yè)務(wù)結(jié)算怎么辦?
  • MQ 是高可用的,消息發(fā)出去了,但是優(yōu)惠券結(jié)算業(yè)務(wù)報(bào)錯(cuò)了怎么辦?因?yàn)檫@個(gè)時(shí)候是異步的,也不好去回滾
  • 消息正常發(fā)出去,消費(fèi)者也接收到了,訂單系統(tǒng)、優(yōu)惠券系統(tǒng)都正常執(zhí)行完了,積分業(yè)務(wù)報(bào)錯(cuò)了導(dǎo)致積分沒(méi)結(jié)算,那這個(gè)訂單的數(shù)據(jù)就不一致了

要解決上述問(wèn)題,就是要保證消息一定要可靠地被消費(fèi),那么我們可以來(lái)分析下消息有哪些步驟會(huì)出問(wèn)題

RabbitMQ 發(fā)送的消息是這樣的 , 消息被生產(chǎn)者發(fā)到指定的交換機(jī)根據(jù)路由規(guī)則路由到綁定的隊(duì)列,然后推送給消費(fèi)者 。
在這里插入圖片描述

在這個(gè)過(guò)程中,可能會(huì)出一下問(wèn)題

  • 生產(chǎn)者消息沒(méi)到交換機(jī),相當(dāng)于生產(chǎn)者弄丟消息
  • 交換機(jī)沒(méi)有把消息路由到隊(duì)列,相當(dāng)于生產(chǎn)者弄丟消息
  • RabbitMQ 宕機(jī)導(dǎo)致隊(duì)列、隊(duì)列中的消息丟失,相當(dāng)于 RabbitMQ 弄丟消息
  • 消費(fèi)者消費(fèi)出現(xiàn)異常,業(yè)務(wù)沒(méi)執(zhí)行,相當(dāng)于消費(fèi)者弄丟消息

下面是單消費(fèi)實(shí)例的解決方案

多實(shí)例的先留個(gè)坑,以后再填

生產(chǎn)者弄丟消息

RabbitMQ 提供了確認(rèn)和回退機(jī)制,有一個(gè)異步監(jiān)聽(tīng)機(jī)制,每次發(fā)送消息,如果成功/未成功發(fā)送到交換機(jī)都可以觸發(fā)一個(gè)監(jiān)聽(tīng)ConfirmCallback(),從交換機(jī)路由到隊(duì)列失敗也會(huì)有一個(gè)監(jiān)聽(tīng)ReturnsCallback()。只需要開(kāi)啟這兩個(gè)監(jiān)聽(tīng)機(jī)制,使用記錄日志、發(fā)送郵件通知、落庫(kù)定時(shí)任務(wù)掃描重發(fā)這些應(yīng)對(duì)策略

生產(chǎn)者弄丟數(shù)據(jù)其實(shí)及其罕見(jiàn),落庫(kù)定時(shí)任務(wù)掃描重發(fā)工作量大,一般記錄日志后,發(fā)郵件給對(duì)應(yīng)人員,補(bǔ)充數(shù)據(jù)庫(kù)數(shù)據(jù)即可

RabbitMQ弄丟消息

宕機(jī)重啟不開(kāi)啟持久化的情況下 RabbitMQ 重啟之后所有隊(duì)列和消息都會(huì)消失,所以我們創(chuàng)建隊(duì)列時(shí)設(shè)置持久化

消費(fèi)者弄丟消息

RabbitMQ 給我們提供了消費(fèi)者應(yīng)答(ack)機(jī)制,默認(rèn)情況下這個(gè)機(jī)制是自動(dòng)應(yīng)答,只要消息推送到消費(fèi)者就會(huì)自動(dòng) ack ,然后 RabbitMQ 刪除隊(duì)列中的消息。啟用手動(dòng)應(yīng)答之后我們?cè)谙M(fèi)端調(diào)用 API 手動(dòng) ack 確認(rèn)之后,RabbitMQ 才會(huì)從隊(duì)列刪除這條消息 。

開(kāi)啟手動(dòng)ack,在業(yè)務(wù)處理完成之后手動(dòng)ack即可,如果在業(yè)務(wù)處理過(guò)程中出異常了,隊(duì)列會(huì)給消費(fèi)者重推,也要注意重推導(dǎo)致的循環(huán)異常,可以配置重試次數(shù)策略。

消息重復(fù)消費(fèi)(冪等性)

這個(gè)也是生產(chǎn)環(huán)境業(yè)務(wù)中經(jīng)常出現(xiàn)的場(chǎng)景,重復(fù)消費(fèi)也要從兩方面分析,為什么會(huì)出現(xiàn)重復(fù)消費(fèi)

生產(chǎn)時(shí)消息重復(fù)

在網(wǎng)絡(luò)波動(dòng)的情況下,生產(chǎn)者給MQ服務(wù)器發(fā)送消息,由于網(wǎng)絡(luò)原因?qū)е律a(chǎn)者沒(méi)有收到ACK確認(rèn)消息,但是MQ服務(wù)器實(shí)際上已經(jīng)接收到了消息,在這種情況下生產(chǎn)者就會(huì)重新發(fā)送一遍剛才的消息。

此時(shí)重發(fā)是MQ-client發(fā)起的,消息的處理是MQ-server,為了避免broker落地重復(fù)的消息,對(duì)每條消息,MQ系統(tǒng)內(nèi)部必須生成一個(gè)inner-msg-id,作為去重和冪等的依據(jù),這個(gè)內(nèi)部消息ID的特性是:

  1. 全局唯一
  2. MQ生成,具備業(yè)務(wù)無(wú)關(guān)性,對(duì)消息發(fā)送方和消息接收方屏蔽

有了這個(gè)inner-msg-id,就能保證即使重發(fā),也只有1條消息落到MQ-server的DB中

消費(fèi)時(shí)消息重復(fù)

在消費(fèi)者方面如果出現(xiàn)網(wǎng)絡(luò)問(wèn)題,比如消費(fèi)者對(duì)消息已經(jīng)成功消費(fèi)了,在向MQ服務(wù)器進(jìn)行確認(rèn)的時(shí)候網(wǎng)絡(luò)異常了,這時(shí)候MQ服務(wù)器就沒(méi)有接收到確認(rèn),MQ為了保證消息被消費(fèi),就會(huì)繼續(xù)向消費(fèi)者發(fā)送之前已經(jīng)被消費(fèi)了的消息,這種情況下消費(fèi)者就會(huì)接收到兩條一樣的消息。

我們解決消息重復(fù)消費(fèi)主要是保證消費(fèi)的冪等性,有兩種角度,第一種就是不讓消費(fèi)端執(zhí)行兩次,第二種是讓它重復(fù)消費(fèi)了,但是不會(huì)對(duì)我的業(yè)務(wù)數(shù)據(jù)造成影響就行。通??梢栽诎l(fā)消息的時(shí)候攜帶業(yè)務(wù)唯一id,消費(fèi)成功后保存到redis/db中,消費(fèi)前再檢查下有沒(méi)有這個(gè)ID,有的話就表示已經(jīng)消費(fèi)過(guò)了,或者使用數(shù)據(jù)庫(kù)唯一性主鍵約束,再或者使用cas,最后遇到重復(fù)消息丟棄消息即可

消息堆積
  • 對(duì)生產(chǎn)者發(fā)消息接口進(jìn)行適當(dāng)限流(不太推薦,影響用戶體驗(yàn))
  • 多部署幾臺(tái)消費(fèi)者實(shí)例(推薦)
  • 適當(dāng)增加 prefetch 的數(shù)量,讓消費(fèi)端一次多接受一些消息(推薦,可以和第二種方案一起用)

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

文章標(biāo)題:RabbitMQ順序性、可靠性、重復(fù)消費(fèi)、消息堆積解決方案-創(chuàng)新互聯(lián)
URL標(biāo)題:http://muchs.cn/article34/ddhppe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、營(yíng)銷型網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、微信公眾號(hào)、小程序開(kāi)發(fā)、企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化