日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MQ保证消息的可靠性传输

發(fā)布時(shí)間:2023/12/15 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MQ保证消息的可靠性传输 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

關(guān)注微信公眾號(hào)“蝦米聊吧”,后續(xù)持續(xù)放送“技術(shù)架構(gòu)和資料”干貨!!

前景概要:

我們在使用mq的時(shí)候肯定是希望數(shù)據(jù)不能多也不能少的,不能多即需要考慮mq的重復(fù)消費(fèi)(冪等性)問題。不能少即不能丟失數(shù)據(jù)。

很明顯如果如果你的mq中存放的是非常核心、重要的數(shù)據(jù),比如訂單數(shù)據(jù)、積分流水等,

這些數(shù)據(jù)是必須不能丟的,一旦丟失則會(huì)造成數(shù)據(jù)的一致性問題,可能會(huì)給公司帶來極大損失。

?

丟失數(shù)據(jù)分析:

丟失數(shù)據(jù)一般來說分為2種情況,一種是數(shù)據(jù)已經(jīng)發(fā)送到了mq,但是mq自身把數(shù)據(jù)弄丟了,第二種是我們在消費(fèi)的時(shí)候把數(shù)據(jù)弄丟了,接下來簡單從rabbitmq和kafka來分析一下。

tips

根據(jù)之前的使用場景來看,一般rabbitmq都會(huì)存放一些比較核心業(yè)務(wù)的數(shù)據(jù),理論上是不能弄丟的;

kafka一般用于大數(shù)據(jù)領(lǐng)域,承載較多的可能是一些日志數(shù)據(jù)。

?

?

(1)RabbitMq

?

1)生產(chǎn)者丟失數(shù)據(jù)

?

關(guān)鍵點(diǎn):rabbitmq開啟confirm確認(rèn)機(jī)制后,rabbitmq通過異步回調(diào)的形式告訴生產(chǎn)者是否已接收到。

?

生產(chǎn)者將數(shù)據(jù)發(fā)送到rabbitmq的時(shí)候,可能數(shù)據(jù)就在半路給丟了,因?yàn)榫W(wǎng)絡(luò)問題或者機(jī)宕機(jī)問題等都有可能。

一般來說,要確保發(fā)送給rabbitmq的消息不能丟失,可以開啟confirm模式,在生產(chǎn)者端設(shè)置開啟confirm模式之后,每次寫入mq的消息都會(huì)分配一個(gè)唯一的id,如果寫入了rabbitmq中,rabbitmq則會(huì)回傳一個(gè)ack確認(rèn)消息,告訴你說這個(gè)消息已經(jīng)成功寫入了。如果rabbitmq沒能處理這個(gè)消息,會(huì)回調(diào)你一個(gè)nack接口,告訴你這個(gè)消息接收失敗,你可以重試。而且你可以結(jié)合這個(gè)機(jī)制自己在內(nèi)存里維護(hù)每個(gè)消息id的狀態(tài),如果超過一定時(shí)間還沒接收到這個(gè)消息的回調(diào),那么你可以重發(fā)。

?

2)rabbitmq自身丟失了數(shù)據(jù)

關(guān)鍵點(diǎn):開啟持久化機(jī)制

這個(gè)就是說rabbitmq自己弄丟了數(shù)據(jù),所以我們必須開啟rabbitmq的持久化機(jī)制,當(dāng)消息寫入之后會(huì)持久化到磁盤,即使是rabbitmq自己掛了,恢復(fù)之后會(huì)自動(dòng)讀取之前存儲(chǔ)的數(shù)據(jù),一般數(shù)據(jù)不會(huì)丟。除非極其罕見的是,rabbitmq還沒持久化,自己就掛了,可能導(dǎo)致少量數(shù)據(jù)會(huì)丟失的,但是這個(gè)概率較小。

?

設(shè)置持久化有兩個(gè)步驟:

第一個(gè)是創(chuàng)建queue的時(shí)候?qū)⑵湓O(shè)置為持久化的,這樣就可以保證rabbitmq持久化queue的元數(shù)據(jù),但是不會(huì)持久化queue里的數(shù)據(jù);

第二個(gè)是發(fā)送消息的時(shí)候?qū)⑾⒌膁eliveryMode設(shè)置為2,就是將消息設(shè)置為持久化,此時(shí)rabbitmq就會(huì)將消息持久化到磁盤上去。必須要同時(shí)設(shè)置這兩個(gè)持久化才行,rabbitmq即使掛了,當(dāng)再次重啟的時(shí)候,也會(huì)從磁盤上恢復(fù)queue,恢復(fù)這個(gè)queue里的數(shù)據(jù)。

而且持久化可以跟生產(chǎn)者那邊的confirm機(jī)制配合起來,只有消息被持久化到磁盤之后,才會(huì)通知生產(chǎn)者ack了,所以哪怕是在持久化到磁盤之前,rabbitmq掛了,數(shù)據(jù)丟了,生產(chǎn)者收不到ack,你也是可以自己重發(fā)的。

但是即使開啟了rabbitmq持久化機(jī)制,也有一種可能仍然導(dǎo)致數(shù)據(jù)丟失,就是這個(gè)消息寫到了rabbitmq中,但是還沒來得及持久化到磁盤上,結(jié)果不巧,此時(shí)rabbitmq掛了,就會(huì)導(dǎo)致內(nèi)存里的一點(diǎn)點(diǎn)數(shù)據(jù)會(huì)丟失。

?

3)消費(fèi)端丟失了數(shù)據(jù)

?

關(guān)鍵點(diǎn):關(guān)閉自動(dòng)ack,開啟手動(dòng)ack

?

這個(gè)很容易理解,主要是因?yàn)橄M(fèi)者那一端在消費(fèi)的時(shí)候,剛消費(fèi)到數(shù)據(jù)還沒完成處理過程,結(jié)果消費(fèi)者服務(wù)的進(jìn)程掛了,但是rabbitmq會(huì)認(rèn)為你已經(jīng)消費(fèi)了,此時(shí)這數(shù)據(jù)就丟了。

這個(gè)時(shí)候就需要采用rabbitmq提供的ack機(jī)制,簡單來說,就是你需要關(guān)閉rabbitmq自動(dòng)ack,可以通過一個(gè)api來調(diào)用就行,然后每次你自己代碼里確保處理完成的時(shí)候,然后程序里再執(zhí)行ack。這樣的話,ack的主動(dòng)權(quán)就掌握在我們自己手里了,即使數(shù)據(jù)還沒處理完,也不會(huì)執(zhí)行ack,這樣的話rabbitmq就不會(huì)認(rèn)為這條消息已經(jīng)被消費(fèi)了,所以消息是不會(huì)丟的。

?

(2)Kafka

?

1) 消費(fèi)端弄丟了數(shù)據(jù)

關(guān)鍵點(diǎn):關(guān)閉自動(dòng)提交offset,手動(dòng)提交offset

唯一可能導(dǎo)致消費(fèi)者弄丟數(shù)據(jù)的情況,就是消費(fèi)者消費(fèi)到了這個(gè)消息,然后消費(fèi)者那邊自動(dòng)提交了offset,讓kafka以為你已經(jīng)消費(fèi)了這個(gè)消息,但其實(shí)你還沒處理完程序的邏輯就掛了,此時(shí)這條消息就丟了。

我們都知道kafka默認(rèn)會(huì)自動(dòng)提交offset,因此只要關(guān)閉自動(dòng)提交offset,在處理完之后自己手動(dòng)提交offset,就可以保證數(shù)據(jù)不會(huì)丟。但是此時(shí)可能會(huì)出現(xiàn)另外一個(gè)問題就是重復(fù)消費(fèi),比如說你剛處理完代碼邏輯,還沒來得及提交offset,結(jié)果程序就掛了,此時(shí)肯定會(huì)重復(fù)消費(fèi)一次,因此這個(gè)需要自身在消費(fèi)者那端保證冪等性。

?

2)kafka自己弄丟了數(shù)據(jù)

較常見的一個(gè)場景就是kafka某個(gè)broker宕機(jī),然后重新選舉partition的leader時(shí)候,如果此時(shí)其他的follower分片剛好還有些數(shù)據(jù)沒有同步,結(jié)果這個(gè)時(shí)候leader掛了,然后選舉某個(gè)follower成leader之后,它就會(huì)少了一部分?jǐn)?shù)據(jù)。

?

所以此時(shí)一般是要求起碼設(shè)置如下4個(gè)參數(shù):

給這個(gè)topic設(shè)置replication.factor參數(shù):這個(gè)值必須大于1,要求每個(gè)partition必須有至少2個(gè)副本;

在kafka服務(wù)端設(shè)置min.insync.replicas參數(shù):這個(gè)值必須大于1,這個(gè)是要求一個(gè)leader至少感知到有至少一個(gè)follower還跟自己保持聯(lián)系,沒掉隊(duì),這樣才能確保leader掛了還有一個(gè)follower吧;

在producer端設(shè)置acks=all:這個(gè)是要求每條數(shù)據(jù),必須是寫入所有replica副本之后,才能認(rèn)為是寫成功了;

在producer端設(shè)置retries=MAX(可以設(shè)置一個(gè)比較大的值,重試次數(shù)):這個(gè)是要求一旦寫入失敗,進(jìn)行重試;

?

3)生產(chǎn)者會(huì)不會(huì)弄丟數(shù)據(jù)

?

如果按照上述的思路設(shè)置了ack=all,一定不會(huì)丟,要求是,你的leader接收到消息,所有的follower都同步到了消息之后,才認(rèn)為本次寫成功了。如果沒滿足這個(gè)條件,生產(chǎn)者會(huì)自動(dòng)不斷的重試,重試無限次。

關(guān)注微信公眾號(hào)“蝦米聊吧”,后續(xù)持續(xù)放送“技術(shù)架構(gòu)和資料”干貨!!

? ? ? ? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ?掃碼關(guān)注獲取更多技術(shù)架構(gòu)知識(shí)干貨喲~

?

總結(jié)

以上是生活随笔為你收集整理的MQ保证消息的可靠性传输的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。