溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

消息隊列把消息弄丟了怎么解決

發(fā)布時間:2021-06-24 14:25:13 來源:億速云 閱讀:513 作者:chen 欄目:編程語言

這篇文章主要講解了“消息隊列把消息弄丟了怎么解決”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“消息隊列把消息弄丟了怎么解決”吧!

消息隊列會丟失消息嗎?

答案是肯定的,所以對于業(yè)務(wù)嚴(yán)謹(jǐn)?shù)臄?shù)據(jù),我們要確保其在消息隊列中的安全,不能丟。

要想解決不丟的問題,首先要弄清楚 消息是怎么丟的呢?

丟消息的關(guān)鍵點有3個:

  • Producer 發(fā)送消息的過程

  • 消息隊列的消息存儲

  • Consumer 消費消息的過程

下面挨個看看都是怎么丟的,以及解決方案。

會以 RabbitMQ 和 Kafka 這兩個常用的消息系統(tǒng)來說明。

1. Producer 弄丟消息

Producer 向 MQ 發(fā)消息,很簡單,發(fā)過去就完事兒了。

但是,在發(fā)送圖中是存在危險的,例如網(wǎng)絡(luò)問題等等,導(dǎo)致 MQ 沒有正常收到。

消息隊列把消息弄丟了怎么解決

怎么解決呢? 思路很簡單,讓 MQ 發(fā)一個 接受確認(rèn)聲明(ack) 就行了,就像快遞需要簽收一樣。

例如 RabbitMQ,有兩種方式可以確保發(fā)送消息的安全。

1)事務(wù)消息

Producer 發(fā)送消息之前,先開啟事務(wù),然后再發(fā)送。

如果 RabbitMQ 沒有正常收到消息,Producer 會收到異常信息,回滾事務(wù)。

如果正常接收了,Producer 就提交事務(wù)。

很可靠,但效率低,因為這個事務(wù)模式是同步的,會產(chǎn)生阻塞。

2)confirm 確認(rèn)模式

Producer 開啟 confirm 模式,發(fā)送消息的時候,RabbitMQ 會給這個消息分配一個唯一的 ID。

成功寫入隊列之后,RabbitMQ 會向 Producer 發(fā)送一個 ack 消息,說明此 ID 的消息已經(jīng)成功發(fā)送。

confirm 模式還有一個回調(diào)機(jī)制,Producer 可以準(zhǔn)備一個失敗的接口,供 RabbitMQ 在接收失敗時調(diào)用。

Producer 收到失敗通知,或者超時了,可以執(zhí)行相應(yīng)的處理邏輯,例如重發(fā)。

confirm 模式是異步的,比事務(wù)消息更高效,使用更為廣泛。

Kafka 也是使用的 ack 方式,使用方式很簡單,只要配置:

ack=all

確保 Kafka 在完全接收成功后才發(fā)送確認(rèn)通知,這樣就一定不會發(fā)丟了。

2. MQ 在存儲期間弄丟消息

MQ 成功接收消息之后,需要保存起來,等著 Consumer 消費。

在這個保存期間,也可以能丟失消息。

這通常是由 MQ 故障引起的。

RabbitMQ 想要保障消息不丟,需要開啟持久化,消息就會寫入磁盤。

即使 RabbitMQ 宕機(jī)了,只要磁盤沒事兒,重啟之后還可以重新把消息加載進(jìn)來。

如果想進(jìn)一步的保障消息安全,就需要配置 RabbitMQ 的鏡像集群了,來確保高可用。

Kafka 是天然的分布式系統(tǒng),Topic 分為多個 Partition,每個 Partition 又有多個副本。

消息隊列把消息弄丟了怎么解決

Partition 的多個副本,分為 Leader 和 Follower。

Leader 負(fù)責(zé)處理消息的讀寫,F(xiàn)ollower 負(fù)責(zé)備份。

前面說的 Kafka 配置 ack=all,就是告訴Kafka,Leader 和所有 Follower 全都接收到了,才算發(fā)送 ack 確認(rèn),只有 Leader 自己接收成功是不算的。

否則的話,如果 Leader 接收完成就告訴 Producer OK 了,在 Leader 同步給 Follower 之前,Leader 宕機(jī)了,Kafka 會從 Follower 中選舉出新的 Leader。那么,老 Leader 在臨終前沒有同步的消息就丟失了。

為了保障消息的安全,這 4 個參數(shù)要設(shè)置好:

replication.factor

用于指定 Partition 副本的數(shù)量,必須大于 1,就是至少要有 2 個副本,一個 Leader 一個 Follower。

min.insync.replicas

用于指定幾個副本成功寫入才提交消息,只有提交之后的消息才能被 Consumer 消費。

此值至少大于 1,這樣就保障 Leader 之外至少有一個副本同步到了這條消息,不怕 Leader 宕掉了。

acks=all

用于指定幾個副本接收到消息之后向 Producer 發(fā)送 ack。例如值為 1,表示 Leader 收到就可以了,“all” 表示 “所有副本”,也可以寫 “-1”,等同于 “all”。

retries=999

用于指定 Producer 發(fā)送失敗后的重試次數(shù),可以設(shè)為一個很大的數(shù),表示失敗了就重試,提升發(fā)送成功幾率。

3. Consumer 弄丟消息

消息隊列把消息弄丟了怎么解決

例如 Consumer 成功接收到了消息 “123”,MQ 就會移除這條消息。

但在 Consumer 處理完這條消息之前,宕機(jī)了。

消息隊列把消息弄丟了怎么解決

Consumer 重啟之后繼續(xù)從 MQ 拿消息,這次拿到的就是下一條消息 “124”,那么 “123” 就丟了。

所以,Consumer 只是接收到消息是不夠的,成功處理完成才行。

這就和 MQ 的消費確認(rèn)機(jī)制有關(guān)了。

RabbitMQ 默認(rèn)是 Consumer 成功接收消息之后就發(fā)送 ack 確認(rèn),RabbitMQ 就認(rèn)為消費成功了。

關(guān)閉自動的 Consumer ack 就行,改為手動發(fā)送確認(rèn)通知。

Kafka 的 Consumer 發(fā)送的不是 ack 確認(rèn),而是 offset,告訴 Kafka 已經(jīng)消費到哪個位置了。

默認(rèn)是 Consumer 接收后自動提交 offset,所以也需要關(guān)閉,改為手動提交。

小結(jié)一下,要想消息不丟,需要發(fā)消息的時候確認(rèn)發(fā)送成功了,MQ 存儲的時候要是高可靠的,Consumer 消費的時候,不能接收之后就確認(rèn),真正處理完成才行。

感謝各位的閱讀,以上就是“消息隊列把消息弄丟了怎么解決”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對消息隊列把消息弄丟了怎么解決這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI