這篇文章主要講解了“消息隊(duì)列把消息弄丟了怎么解決”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“消息隊(duì)列把消息弄丟了怎么解決”吧!
創(chuàng)新互聯(lián)專注于濰坊企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,電子商務(wù)商城網(wǎng)站建設(shè)。濰坊網(wǎng)站建設(shè)公司,為濰坊等地區(qū)提供建站服務(wù)。全流程按需求定制開(kāi)發(fā),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
消息隊(duì)列會(huì)丟失消息嗎?
答案是肯定的,所以對(duì)于業(yè)務(wù)嚴(yán)謹(jǐn)?shù)臄?shù)據(jù),我們要確保其在消息隊(duì)列中的安全,不能丟。
要想解決不丟的問(wèn)題,首先要弄清楚 消息是怎么丟的呢?
丟消息的關(guān)鍵點(diǎn)有3個(gè):
Producer 發(fā)送消息的過(guò)程
消息隊(duì)列的消息存儲(chǔ)
Consumer 消費(fèi)消息的過(guò)程
下面挨個(gè)看看都是怎么丟的,以及解決方案。
會(huì)以 RabbitMQ 和 Kafka 這兩個(gè)常用的消息系統(tǒng)來(lái)說(shuō)明。
Producer 向 MQ 發(fā)消息,很簡(jiǎn)單,發(fā)過(guò)去就完事兒了。
但是,在發(fā)送圖中是存在危險(xiǎn)的,例如網(wǎng)絡(luò)問(wèn)題等等,導(dǎo)致 MQ 沒(méi)有正常收到。
怎么解決呢?思路很簡(jiǎn)單,讓 MQ 發(fā)一個(gè) 接受確認(rèn)聲明(ack)就行了,就像快遞需要簽收一樣。
例如 RabbitMQ,有兩種方式可以確保發(fā)送消息的安全。
1)事務(wù)消息
Producer 發(fā)送消息之前,先開(kāi)啟事務(wù),然后再發(fā)送。
如果 RabbitMQ 沒(méi)有正常收到消息,Producer 會(huì)收到異常信息,回滾事務(wù)。
如果正常接收了,Producer 就提交事務(wù)。
很可靠,但效率低,因?yàn)檫@個(gè)事務(wù)模式是同步的,會(huì)產(chǎn)生阻塞。
2)confirm 確認(rèn)模式
Producer 開(kāi)啟 confirm 模式,發(fā)送消息的時(shí)候,RabbitMQ 會(huì)給這個(gè)消息分配一個(gè)唯一的 ID。
成功寫(xiě)入隊(duì)列之后,RabbitMQ 會(huì)向 Producer 發(fā)送一個(gè) ack 消息,說(shuō)明此 ID 的消息已經(jīng)成功發(fā)送。
confirm 模式還有一個(gè)回調(diào)機(jī)制,Producer 可以準(zhǔn)備一個(gè)失敗的接口,供 RabbitMQ 在接收失敗時(shí)調(diào)用。
Producer 收到失敗通知,或者超時(shí)了,可以執(zhí)行相應(yīng)的處理邏輯,例如重發(fā)。
confirm 模式是異步的,比事務(wù)消息更高效,使用更為廣泛。
Kafka也是使用的 ack 方式,使用方式很簡(jiǎn)單,只要配置:
ack=all
確保 Kafka 在完全接收成功后才發(fā)送確認(rèn)通知,這樣就一定不會(huì)發(fā)丟了。
MQ 成功接收消息之后,需要保存起來(lái),等著 Consumer 消費(fèi)。
在這個(gè)保存期間,也可以能丟失消息。
這通常是由 MQ 故障引起的。
RabbitMQ想要保障消息不丟,需要開(kāi)啟持久化,消息就會(huì)寫(xiě)入磁盤(pán)。
即使 RabbitMQ 宕機(jī)了,只要磁盤(pán)沒(méi)事兒,重啟之后還可以重新把消息加載進(jìn)來(lái)。
如果想進(jìn)一步的保障消息安全,就需要配置 RabbitMQ 的鏡像集群了,來(lái)確保高可用。
Kafka是天然的分布式系統(tǒng),Topic 分為多個(gè) Partition,每個(gè) Partition 又有多個(gè)副本。
Partition 的多個(gè)副本,分為 Leader 和 Follower。
Leader 負(fù)責(zé)處理消息的讀寫(xiě),F(xiàn)ollower 負(fù)責(zé)備份。
前面說(shuō)的 Kafka 配置 ack=all
,就是告訴Kafka,Leader 和所有 Follower 全都接收到了,才算發(fā)送 ack 確認(rèn),只有 Leader 自己接收成功是不算的。
否則的話,如果 Leader 接收完成就告訴 Producer OK 了,在 Leader 同步給 Follower 之前,Leader 宕機(jī)了,Kafka 會(huì)從 Follower 中選舉出新的 Leader。那么,老 Leader 在臨終前沒(méi)有同步的消息就丟失了。
為了保障消息的安全,這 4 個(gè)參數(shù)要設(shè)置好:
replication.factor
用于指定 Partition 副本的數(shù)量,必須大于 1,就是至少要有 2 個(gè)副本,一個(gè) Leader 一個(gè) Follower。
min.insync.replicas
用于指定幾個(gè)副本成功寫(xiě)入才提交消息,只有提交之后的消息才能被 Consumer 消費(fèi)。
此值至少大于 1,這樣就保障 Leader 之外至少有一個(gè)副本同步到了這條消息,不怕 Leader 宕掉了。
acks=all
用于指定幾個(gè)副本接收到消息之后向 Producer 發(fā)送 ack。例如值為 1,表示 Leader 收到就可以了,“all” 表示 “所有副本”,也可以寫(xiě) “-1”,等同于 “all”。
retries=999
用于指定 Producer 發(fā)送失敗后的重試次數(shù),可以設(shè)為一個(gè)很大的數(shù),表示失敗了就重試,提升發(fā)送成功幾率。
例如 Consumer 成功接收到了消息 “123”,MQ 就會(huì)移除這條消息。
但在 Consumer 處理完這條消息之前,宕機(jī)了。
Consumer 重啟之后繼續(xù)從 MQ 拿消息,這次拿到的就是下一條消息 “124”,那么 “123” 就丟了。
所以,Consumer 只是接收到消息是不夠的,成功處理完成才行。
這就和 MQ 的消費(fèi)確認(rèn)機(jī)制有關(guān)了。
RabbitMQ默認(rèn)是 Consumer 成功接收消息之后就發(fā)送 ack 確認(rèn),RabbitMQ 就認(rèn)為消費(fèi)成功了。
關(guān)閉自動(dòng)的 Consumer ack 就行,改為手動(dòng)發(fā)送確認(rèn)通知。
Kafka的 Consumer 發(fā)送的不是 ack 確認(rèn),而是 offset,告訴 Kafka 已經(jīng)消費(fèi)到哪個(gè)位置了。
默認(rèn)是 Consumer 接收后自動(dòng)提交 offset,所以也需要關(guān)閉,改為手動(dòng)提交。
小結(jié)一下,要想消息不丟,需要發(fā)消息的時(shí)候確認(rèn)發(fā)送成功了,MQ 存儲(chǔ)的時(shí)候要是高可靠的,Consumer 消費(fèi)的時(shí)候,不能接收之后就確認(rèn),真正處理完成才行。
感謝各位的閱讀,以上就是“消息隊(duì)列把消息弄丟了怎么解決”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)消息隊(duì)列把消息弄丟了怎么解決這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!