真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?-創(chuàng)新互聯(lián)

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

創(chuàng)新互聯(lián)是專業(yè)的臨海網(wǎng)站建設(shè)公司,臨海接單;提供成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè),網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行臨海網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊,希望更多企業(yè)前來合作!

一、前言

我們小伙伴應(yīng)該都聽說夠消息中間件MQ,如:RabbitMQ,RocketMQ,Kafka等。引入中間件的好處可以起到抗高并發(fā),削峰,業(yè)務(wù)解耦的作用。

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

如上圖:

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

(2)物流服務(wù)監(jiān)聽MQ中間件消息,從而進(jìn)行消費

二、分析問題

小伙伴們對此會有些疑問,訂單服務(wù)發(fā)起消息服務(wù),返回成功不就成功了嗎?如下面的偽代碼:

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

上面代碼中,一般發(fā)送消息就是這么寫的,小伙伴們覺得有什么問題嗎?

下邊說一個場景,如果MQ服務(wù)器突然宕機(jī)了會出現(xiàn)什么情況?是不是我們訂單服務(wù)發(fā)過去的消息全部沒有了嗎?是的,一般MQ中間件為了提高系統(tǒng)的吞吐量會把消息保存在內(nèi)存中,如果不作其他處理,MQ服務(wù)器一旦宕機(jī),消息將全部丟失。這個是業(yè)務(wù)不允許的,造成很大的影響。

三、持久化

有經(jīng)驗的小伙伴會說,我知道一個方法就是把消息持久化,RabbitMQ中發(fā)消息的時候會有個durable參數(shù)可以設(shè)置,設(shè)置為true,就會持久化。

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

這樣的話MQ服務(wù)器即使宕機(jī),重啟后磁盤文件中有消息的存儲,這樣就不會丟失了吧。是的這樣就一定概率的保障了消息不丟失。

但還會有個場景,就是消息剛剛保存到MQ內(nèi)存中,但還沒有來得及更新到磁盤文件中,突然宕機(jī)了。(我靠,這個時間這么短,也會出現(xiàn),概率太低了吧),這個場景在持續(xù)的大量消息投遞的過程中,會很常見。

那怎么辦?我們?nèi)绾巫鞑拍鼙U弦欢〞志没酱疟P上面呢?

四、confirm機(jī)制

上面問題出現(xiàn)在,沒有人告訴我們持久化是否成功。好在很多MQ有回調(diào)通知的特性,RabbitMQ就有confirm機(jī)制來通知我們是否持久化成功?

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

confirm機(jī)制的原理:

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

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

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

上面的偽代碼,有兩個處理消息方式,就是ack回調(diào)和nack回調(diào)。

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

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

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

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

說了這么多,還是沒法確保,那怎么辦呢???

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

其實本質(zhì)的原因是無法確定是否持久化?那我們是不是可以自己讓消息持久化呢?答案是可以的,我們的方案再一步的演化。

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

上圖流程:

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

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

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

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

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

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

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

這樣的話方案就比較完美了,保障了100%的消息不丟失(當(dāng)然不包含磁盤也壞了,可以做主從方案)。

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

那就要要求消費者一定在消費的時候保障冪等性!

六、冪等含義

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

6.1、為什么要有冪等這種場景?

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

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

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

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

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

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

6.2、樂觀鎖方案

借鑒數(shù)據(jù)庫的樂觀鎖機(jī)制,如:

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

根據(jù)version版本,也就是在操作庫存前先獲取當(dāng)前商品的version版本號,然后操作的時候帶上此version號。我們梳理下,我們第一次操作庫存時,得到version為1,調(diào)用庫存服務(wù)version變成了2;但返回給訂單服務(wù)出現(xiàn)了問題,訂單服務(wù)又一次發(fā)起調(diào)用庫存服務(wù),當(dāng)訂單服務(wù)傳如的version還是1,再執(zhí)行上面的sql語句時,就不會執(zhí)行;因為version已經(jīng)變?yōu)?了,where條件就不成立。這樣就保證了不管調(diào)用幾次,只會真正的處理一次。

6.3、唯一ID + 指紋碼

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

如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?

  • 唯一ID就是業(yè)務(wù)表的唯一的主鍵,如商品ID

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

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

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

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

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

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

6.4、Redis原子操作

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

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

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

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

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

以上我們結(jié)束了冪等相關(guān)的解決方案,以后文章中我們會重點介紹方案的實現(xiàn)。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


新聞標(biāo)題:如何保障消息中間件100%消息投遞成功?如何保證消息冪等性?-創(chuàng)新互聯(lián)
本文地址:http://weahome.cn/article/hhiip.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部