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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

消息队列中数据丢失了怎么办

發(fā)布時(shí)間:2023/12/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 消息队列中数据丢失了怎么办 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1、面試題

如何保證消息的可靠性傳輸(如何處理消息丟失的問(wèn)題)?

2、面試官心里分析

這個(gè)是肯定的,用mq有個(gè)基本原則,就是數(shù)據(jù)不能多一條,也不能少一條,不能多,就是剛才說(shuō)的重復(fù)消費(fèi)和冪等性問(wèn)題。不能少,就是說(shuō)這數(shù)據(jù)別搞丟了。那這個(gè)問(wèn)題你必須得考慮一下。

如果說(shuō)你這個(gè)是用mq來(lái)傳遞非常核心的消息,比如說(shuō)計(jì)費(fèi),扣費(fèi)的一些消息,因?yàn)槲乙郧霸O(shè)計(jì)和研發(fā)過(guò)一個(gè)公司非常核心的廣告平臺(tái),計(jì)費(fèi)系統(tǒng),計(jì)費(fèi)系統(tǒng)是很重的一個(gè)業(yè)務(wù),操作是很耗時(shí)的。所以說(shuō)廣告系統(tǒng)整體的架構(gòu)里面,實(shí)際上是將計(jì)費(fèi)做成異步化的,然后中間就是加了一個(gè)MQ。

我們當(dāng)時(shí)為了確保說(shuō)這個(gè)MQ傳遞過(guò)程中絕對(duì)不會(huì)把計(jì)費(fèi)消息給弄丟,花了很多的精力。廣告主投放了一個(gè)廣告,明明說(shuō)好了,用戶點(diǎn)擊一次扣費(fèi)1塊錢(qián)。結(jié)果要是用戶動(dòng)不動(dòng)點(diǎn)擊了一次,扣費(fèi)的時(shí)候搞的消息丟了,我們公司就會(huì)不斷的少幾塊錢(qián),幾塊錢(qián),積少成多,這個(gè)就對(duì)公司是一個(gè)很大的損失。

3、面試題剖析

這個(gè)丟數(shù)據(jù),mq一般分為兩種,要么是mq自己弄丟了,要么是我們消費(fèi)的時(shí)候弄丟了。咱們從rabbitmq和kafka分別來(lái)分析一下吧!

rabbitmq這種mq,一般來(lái)說(shuō)都是承載公司的核心業(yè)務(wù)的,數(shù)據(jù)是絕對(duì)不能弄丟的。

(1)rabbitmq

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

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

此時(shí)可以選擇用rabbitmq提供的事務(wù)功能,就是生產(chǎn)者發(fā)送數(shù)據(jù)之前開(kāi)啟rabbitmq事務(wù)(channel.txSelect),然后發(fā)送消息,如果消息沒(méi)有成功被rabbitmq接收到,那么生產(chǎn)者會(huì)收到異常報(bào)錯(cuò),此時(shí)就可以回滾事務(wù)(channel.txRollback),然后重試發(fā)送消息;如果收到了消息,那么可以提交事務(wù)(channel.txCommit)。但是問(wèn)題是,rabbitmq事務(wù)機(jī)制一搞,基本上吞吐量會(huì)下來(lái),因?yàn)樘男阅堋?/p>

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

事務(wù)機(jī)制和cnofirm機(jī)制最大的不同在于,事務(wù)機(jī)制是同步的,你提交一個(gè)事務(wù)之后會(huì)阻塞在那兒,但是confirm機(jī)制是異步的,你發(fā)送個(gè)消息之后就可以發(fā)送下一個(gè)消息,然后那個(gè)消息rabbitmq接收了之后會(huì)異步回調(diào)你一個(gè)接口通知你這個(gè)消息接收到了。

所以一般在生產(chǎn)者這塊避免數(shù)據(jù)丟失,都是用confirm機(jī)制的。

?

?

?

2)rabbitmq弄丟了數(shù)據(jù)

就是rabbitmq自己弄丟了數(shù)據(jù),這個(gè)你必須開(kāi)啟rabbitmq的持久化,就是消息寫(xiě)入之后會(huì)持久化到磁盤(pán),哪怕是rabbitmq自己掛了,恢復(fù)之后會(huì)自動(dòng)讀取之前存儲(chǔ)的數(shù)據(jù),一般數(shù)據(jù)不會(huì)丟。除非極其罕見(jiàn)的是,rabbitmq還沒(méi)持久化,自己就掛了,可能導(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ì)將消息持久化到磁盤(pán)上去。必須要同時(shí)設(shè)置這兩個(gè)持久化才行,rabbitmq哪怕是掛了,再次重啟,也會(huì)從磁盤(pán)上重啟恢復(fù)queue,恢復(fù)這個(gè)queue里的數(shù)據(jù)。

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

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

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

rabbitmq如果丟失了數(shù)據(jù),主要是因?yàn)槟阆M(fèi)的時(shí)候,剛消費(fèi)到,還沒(méi)處理,結(jié)果進(jìn)程掛了,比如重啟了,那么就尷尬了,rabbitmq認(rèn)為你都消費(fèi)了,這數(shù)據(jù)就丟了。

這個(gè)時(shí)候得用rabbitmq提供的ack機(jī)制,簡(jiǎn)單來(lái)說(shuō),就是你關(guān)閉rabbitmq自動(dòng)ack,可以通過(guò)一個(gè)api來(lái)調(diào)用就行,然后每次你自己代碼里確保處理完的時(shí)候,再程序里ack一把。這樣的話,如果你還沒(méi)處理完,不就沒(méi)有ack?那rabbitmq就認(rèn)為你還沒(méi)處理完,這個(gè)時(shí)候rabbitmq會(huì)把這個(gè)消費(fèi)分配給別的consumer去處理,消息是不會(huì)丟的。

(2)kafka

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

唯一可能導(dǎo)致消費(fèi)者弄丟數(shù)據(jù)的情況,就是說(shuō),你那個(gè)消費(fèi)到了這個(gè)消息,然后消費(fèi)者那邊自動(dòng)提交了offset,讓kafka以為你已經(jīng)消費(fèi)好了這個(gè)消息,其實(shí)你剛準(zhǔn)備處理這個(gè)消息,你還沒(méi)處理,你自己就掛了,此時(shí)這條消息就丟咯。

這不是一樣么,大家都知道kafka會(huì)自動(dòng)提交offset,那么只要關(guān)閉自動(dòng)提交offset,在處理完之后自己手動(dòng)提交offset,就可以保證數(shù)據(jù)不會(huì)丟。但是此時(shí)確實(shí)還是會(huì)重復(fù)消費(fèi),比如你剛處理完,還沒(méi)提交offset,結(jié)果自己掛了,此時(shí)肯定會(huì)重復(fù)消費(fèi)一次,自己保證冪等性就好了。

生產(chǎn)環(huán)境碰到的一個(gè)問(wèn)題,就是說(shuō)我們的kafka消費(fèi)者消費(fèi)到了數(shù)據(jù)之后是寫(xiě)到一個(gè)內(nèi)存的queue里先緩沖一下,結(jié)果有的時(shí)候,你剛把消息寫(xiě)入內(nèi)存queue,然后消費(fèi)者會(huì)自動(dòng)提交offset。

然后此時(shí)我們重啟了系統(tǒng),就會(huì)導(dǎo)致內(nèi)存queue里還沒(méi)來(lái)得及處理的數(shù)據(jù)就丟失了。

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

這塊比較常見(jiàn)的一個(gè)場(chǎng)景,就是kafka某個(gè)broker宕機(jī),然后重新選舉partiton的leader時(shí)。大家想想,要是此時(shí)其他的follower剛好還有些數(shù)據(jù)沒(méi)有同步,結(jié)果此時(shí)leader掛了,然后選舉某個(gè)follower成leader之后,他不就少了一些數(shù)據(jù)?這就丟了一些數(shù)據(jù)啊。

生產(chǎn)環(huán)境也遇到過(guò),我們也是,之前kafka的leader機(jī)器宕機(jī)了,將follower切換為leader之后,就會(huì)發(fā)現(xiàn)說(shuō)這個(gè)數(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)系,沒(méi)掉隊(duì),這樣才能確保leader掛了還有一個(gè)follower吧!

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

在producer端設(shè)置retries=MAX(很大很大很大的一個(gè)值,無(wú)限次重試的意思):這個(gè)是要求一旦寫(xiě)入失敗,就無(wú)限重試,卡在這里了。

我們生產(chǎn)環(huán)境就是按照上述要求配置的,這樣配置之后,至少在kafka broker端就可以保證在leader所在broker發(fā)生故障,進(jìn)行l(wèi)eader切換時(shí),數(shù)據(jù)不會(huì)丟失。

?

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

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

總結(jié):

首先mq丟數(shù)據(jù)分三種情況1.生產(chǎn)者網(wǎng)mq寫(xiě)數(shù)據(jù)時(shí),2.mq丟數(shù)據(jù)(如宕機(jī))3.消費(fèi)者丟數(shù)據(jù)(consumer宕機(jī))先說(shuō)rabitmq: 1)生產(chǎn)者丟數(shù)據(jù)1.rabitmq提供事物功能(百分百不會(huì)丟數(shù)據(jù))但是會(huì)降低吞吐量(同步事物會(huì)阻塞)2.開(kāi)啟confirm模式,異步ack機(jī)制(失敗消息重發(fā))、 2)rabbitmq弄丟了數(shù)據(jù)1.開(kāi)啟rabbitmq的持久化(除非極其罕見(jiàn)的是,rabbitmq還沒(méi)持久化,自己就掛了,可能導(dǎo)致少量數(shù)據(jù)會(huì)丟失的,但是這個(gè)概率較小)2.持久化配合confirm模式,只有當(dāng)所有的消息持久化到硬盤(pán)之后才返回ack,可以保證百分百不會(huì)丟失數(shù)據(jù) 3)消費(fèi)端弄丟了數(shù)據(jù)1.rabbitmq提供的ack機(jī)制(但是要關(guān)閉rabitmq的自動(dòng)ack機(jī)制,當(dāng)consumer處理完消息之后手動(dòng)ack)
再說(shuō)kafka:
1)消費(fèi)端弄丟了數(shù)據(jù)1.關(guān)閉自動(dòng)提交offset,在處理完之后自己手動(dòng)提交offset,就可以保證數(shù)據(jù)不會(huì)丟。但是此時(shí)確實(shí)還是會(huì)重復(fù)消費(fèi)(冪等性) 2)kafka弄丟了數(shù)據(jù)1.主從切換的時(shí)候丟數(shù)據(jù)。解決辦法時(shí)調(diào)參數(shù),當(dāng)produce發(fā)送消息給kafaka失敗是就無(wú)限重試,只有當(dāng)消息全部到達(dá)rplicate副本時(shí)才返回ack.

?

轉(zhuǎn)載于:https://www.cnblogs.com/UncleWang001/p/10606071.html

總結(jié)

以上是生活随笔為你收集整理的消息队列中数据丢失了怎么办的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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