欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

如何保障消息中間件不丟失

這篇文章主要介紹“如何保障消息中間件不丟失”,在日常操作中,相信很多人在如何保障消息中間件不丟失問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何保障消息中間件不丟失”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

創(chuàng)新互聯(lián),是成都地區(qū)的互聯(lián)網(wǎng)解決方案提供商,用心服務(wù)為企業(yè)提供網(wǎng)站建設(shè)、app軟件開發(fā)、微信小程序開發(fā)、系統(tǒng)按需網(wǎng)站建設(shè)和微信代運營服務(wù)。經(jīng)過數(shù)10年的沉淀與積累,沉淀的是技術(shù)和服務(wù),讓客戶少走彎路,踏實做事,誠實做人,用情服務(wù),致力做一個負責任、受尊敬的企業(yè)。對客戶負責,就是對自己負責,對企業(yè)負責。

前言

RabbitMQ,RocketMQ,Kafka 等。引入中間件的好處可以起到抗高并發(fā),削峰,業(yè)務(wù)解耦的作用。

如何保障消息中間件不丟失

如上圖

  1. 訂單服務(wù)投遞消息給MQ中間件

  2. 庫存服務(wù)監(jiān)聽MQ中間件消息,從而進行消費

之前公司在業(yè)務(wù)搭建的時候用的就是這種MQ解耦機制,那么如何保障將訂單服務(wù)的消息成功投遞給MQ中間件,保證消息的可靠性?

問題

可能會有人疑問,訂單服務(wù)發(fā)起消息,返回成功不就OK了嗎?下面有一個Demo代碼

如何保障消息中間件不丟失

一般的發(fā)送消息都是這么寫的,但是有一個場景必須在業(yè)務(wù)搭建之初就要考慮。如果MQ服務(wù)器突然宕機了呢?我們發(fā)送的消息是不是就沒有了呢?

是的!一般MQ中間件為了保證提供系統(tǒng)的吞吐量會把消息保存在內(nèi)存中,如果不作其他處理,MQ一旦宕機,消息就會全部丟失。這個在業(yè)務(wù)中是絕對不允許的,造成的影響是非常大的!

那么如何解決這個問題?

消息持久化

MQ中發(fā)消息的時候會有一個durable參數(shù)可以設(shè)置,設(shè)置為true,就會持久化!

如何保障消息中間件不丟失

這樣的話MQ服務(wù)器及時宕機,重啟后磁盤文件中有消息的存儲,這樣就不會丟失了,但是這種方式也僅僅只是有概率的消息不丟失。

如果消息剛剛保存到MQ內(nèi)存中,還沒來得及更新到磁盤中,突然宕機了(一般高并發(fā)情況下發(fā)生幾率會很高),尤其是大量消息投遞的過程中。

如何才能做到一定持久化到磁盤中呢?

confirm機制

上面的問題主要在于,沒有人告訴我們持久化是否成功。好在MQ有回調(diào)通知特性,confirm機制來通知我們是否持久化成功。

如何保障消息中間件不丟失

confirm機制原理

  • 消息生產(chǎn)者把消息發(fā)送給MQ,如果接收成功,MQ會返回一個ack消息- 給生產(chǎn)者。

  • 如果消息不成功,MQ會返回一個nack消息給生產(chǎn)者。

如何保障消息中間件不丟失

上面的demo代碼中有兩個確認機制,一個ACK回調(diào),一個NACK回調(diào)。

這樣是不是就可以100%確保消息不丟失了呢?

吞吐量問題嚴重

試想一下,如果我們生產(chǎn)者每發(fā)一條消息,都要 MQ 持久化到磁盤中,然后再發(fā)起 ack 或 nack 的回調(diào)。這樣的話是不是我們 MQ 的吞吐量很不高,因為每次都要把消息持久化到磁盤中。寫入磁盤這個動作是很慢的。這個在高并發(fā)場景下是不能夠接受的,吞吐量太低了。

所以 MQ 持久化磁盤真實的實現(xiàn),是通過異步調(diào)用處理的,他是有一定的機制,如:等到有幾千條消息的時候,會一次性的刷盤到磁盤上面。而不是每來一條消息,就刷盤一次。

所以 comfirm 機制其實是一個異步監(jiān)聽的機制,是為了保證系統(tǒng)的高吞吐量,這樣就導致了還是不能夠 100%保障消息不丟失,因為即使加上了 confirm 機制,消息在 MQ 內(nèi)存中還沒有刷盤到磁盤就宕機了,還是沒法處理。

消息提前持久化 + 定時任務(wù)

其實本質(zhì)的原因是無法確定是否持久化。

ps:圖畫的有點辣雞~~~~

如何保障消息中間件不丟失

流程操作

  1. 訂單服務(wù)生產(chǎn)者再投遞消息之前,先把消息持久化到 redis 或 DB 中,建議 redis,高性能。消息的狀態(tài)為發(fā)送中。

  2. confirm 機制監(jiān)聽消息是否發(fā)送成功?如 ack 成功消息,刪除 redis 中此消息。

  3. 如果 nack 不成功的消息,這個可以根據(jù)自身的業(yè)務(wù)選擇是否重發(fā)此消息。也可以刪除此消息,由自己的業(yè)務(wù)決定。

  4. 這邊加了個定時任務(wù),來拉取隔一定時間了,消息狀態(tài)還是為發(fā)送中的,這個狀態(tài)就表明,訂單服務(wù)是沒有收到 ack 成功消息。

  5. 定時任務(wù)會作補償性的投遞消息。這個時候如果 MQ 回調(diào) ack 成功接收了,再把 redis 中此消息刪除。

補償機制方案

這樣的機制其實就是一個補償機制,我不管 MQ 有沒有真正的接收到,只要我的 redis 中的消息狀態(tài)也是為==發(fā)送中==,就表示此消息沒有正確成功投遞。再啟動定時任務(wù)去監(jiān)控,發(fā)起補償投遞。

機制的優(yōu)化

當然定時任務(wù)那邊我們還可以加上一個補償?shù)拇螖?shù),如果大于 3 次,還是沒有收到 ack 消息,那就直接把消息的狀態(tài)設(shè)置為【失敗】,由人工去排查到底是為什么?

這樣的話方案就比較完美了,保障了 100%的消息不丟失、磁盤要是壞了,那就沒法保障了,就要考慮集群方案。

方案問題

不過這樣的方案,就會有可能發(fā)送多次相同的消息,很有可能 MQ 已經(jīng)收到了消息,就是 ack 消息回調(diào)時出現(xiàn)網(wǎng)絡(luò)故障,沒有讓生產(chǎn)者收到。那就要要求消費者一定在消費的時候保障冪等性

冪等含義

我們先了解一下什么叫冪等?在分布式應(yīng)用中,冪等是非常重要的,也就是相同條件下對一個業(yè)務(wù)的操作,不管操作多少次,結(jié)果都是一樣。

分布式冪等

為什么要有冪等這種場景?因為在大的系統(tǒng)中,都是分布式部署,如:訂單業(yè)務(wù)庫存業(yè)務(wù)有可能都是獨立部署的,都是單獨的服務(wù)。用戶下訂單,會調(diào)用到訂單服務(wù)和庫存服務(wù)。

分布式異常問題

因為分布式部署,很有可能在調(diào)用庫存服務(wù)時,因為網(wǎng)絡(luò)等原因,訂單服務(wù)調(diào)用失敗,但其實庫存服務(wù)已經(jīng)處理完成。只是返回給訂單服務(wù)處理結(jié)果時出現(xiàn)了異常。這個時候一般系統(tǒng)會作補償方案,也就是訂單服務(wù)再此放起庫存服務(wù)的調(diào)用,庫存減 1。

update m_goods set count = count - 1 where g_id=10

這樣就出現(xiàn)了問題,其實上一次調(diào)用已經(jīng)減了 1,只是訂單服務(wù)沒有收到處理結(jié)果。現(xiàn)在又調(diào)用一次,又要減 1,這樣就不符合業(yè)務(wù)了,多扣了。

冪等這個概念就是,不管庫存服務(wù)在相同條件下調(diào)用幾次,處理結(jié)果都一樣。這樣才能保證補償方案的可行性。

樂觀鎖方案

借鑒網(wǎng)上的樂觀鎖方案,例如:

update m_goods set count = count -1 , version = version + 1 where g_id=2 and version = 1

根據(jù) version 版本,也就是在操作庫存前先獲取當前商品的 version 版本號,然后操作的時候帶上此 version 號。我們梳理下,我們第一次操作庫存時,得到 version 結(jié)果如下:

  1. 調(diào)用庫存服務(wù) version 變成了 2;但返回給訂單服務(wù)出現(xiàn)了問題,訂單服務(wù)又一次發(fā)起調(diào)用庫存服務(wù),當訂單服務(wù)傳如的 version 還是 1,再執(zhí)行上面的 sql 語句時,就不會執(zhí)行;因為 version 已經(jīng)變?yōu)?2 了,where 條件就不成立。這樣就保證了不管調(diào)用幾次,只會真正的處理一次。

唯一 ID + 指紋碼

此方案是網(wǎng)上找到的一篇博客所寫的,感覺不錯。

原理就是利用數(shù)據(jù)庫主鍵去重,業(yè)務(wù)完成后插入主鍵標識~

select count(1) from t_check where ID = 唯一ID + 指紋碼
  • 唯一 ID 就是業(yè)務(wù)表的唯一的主鍵,如商品 ID

  • 指紋碼就是為了區(qū)別每次正常操作的碼,每次操作時生成指紋碼;可以用時間戳+業(yè)務(wù)編號的方式。

上面的 sql 語句:

  • 返回如果為 0 表示沒有操作過,那業(yè)務(wù)操作后就可以 insert into t_check(唯一 ID+指紋碼)

  • 返回如果大于 0 表示操作過,就直接返回

好處:實現(xiàn)簡單

壞處:高并發(fā)下數(shù)據(jù)庫瓶頸

解決方案:根據(jù) ID 進行分庫分表進行算法路由

redis 原子操作(推薦使用)

利用 redis 的原子操作,做個操作完成的標記。這個性能就比較好。但會遇到一些問題。

問題:我們是否需要把業(yè)務(wù)結(jié)果進行數(shù)據(jù)落庫,如果落庫,關(guān)鍵解決的問題時數(shù)據(jù)庫和 redis 操作如何做到原子性?

這個意思就是庫存減 1 了,但 redis 進行操作完成標記時,失敗了怎么辦?也就是一定要保證落庫和 redis 要么一起成功,要么一起失敗

第二:如果不進行落庫,那么都存儲到緩存中,如何設(shè)置定時同步策略?

這個意思就是庫存減 1,不落庫,直接先操作 redis 操作完成標記,然后由另外的同步服務(wù)進行庫存落庫,這個就是增加了系統(tǒng)復雜性,而且同步策略的設(shè)置。

到此,關(guān)于“如何保障消息中間件不丟失”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

本文題目:如何保障消息中間件不丟失
瀏覽路徑:http://chinadenli.net/article40/gicgeo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、網(wǎng)站排名網(wǎng)頁設(shè)計公司、響應(yīng)式網(wǎng)站、品牌網(wǎng)站設(shè)計網(wǎng)站收錄

廣告

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

網(wǎng)站托管運營