日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁(yè) > 科技  > 軟件

SpringBoot項(xiàng)目保證接口冪等的五種方法!

來源: 責(zé)編: 時(shí)間:2024-06-07 17:18:33 179觀看
導(dǎo)讀1. 冪等概述1.1 深入理解冪等性在計(jì)算機(jī)領(lǐng)域中,冪等(Idempotence)是指任意一個(gè)操作的多次執(zhí)行總是能獲得相同的結(jié)果,不會(huì)對(duì)系統(tǒng)狀態(tài)產(chǎn)生額外影響。在Java后端開發(fā)中,冪等性的實(shí)現(xiàn)通常通過確保方法或服務(wù)調(diào)用的結(jié)果具有確定

1. 冪等概述

1.1 深入理解冪等性

在計(jì)算機(jī)領(lǐng)域中,冪等(Idempotence)是指任意一個(gè)操作的多次執(zhí)行總是能獲得相同的結(jié)果,不會(huì)對(duì)系統(tǒng)狀態(tài)產(chǎn)生額外影響。在Java后端開發(fā)中,冪等性的實(shí)現(xiàn)通常通過確保方法或服務(wù)調(diào)用的結(jié)果具有確定性,無論調(diào)用次數(shù)如何,結(jié)果都是可預(yù)期的。udB28資訊網(wǎng)——每日最新資訊28at.com

上面的定義是目前大多數(shù)文章和書籍對(duì)冪等的描述,然而,在實(shí)際的互聯(lián)網(wǎng)服務(wù)開發(fā)中,冪等性的理論定義與業(yè)務(wù)邏輯間的沖突是常見的。udB28資訊網(wǎng)——每日最新資訊28at.com

例如,考慮查詢操作,當(dāng)A系統(tǒng)調(diào)用B系統(tǒng)的查詢接口時(shí),如果首次調(diào)用由于B系統(tǒng)中的程序錯(cuò)誤而導(dǎo)致業(yè)務(wù)邏輯失敗,即使在程序修復(fù)后系統(tǒng)A重新使用相同參數(shù)進(jìn)行重試,B系統(tǒng)可能仍然返回相同的失敗響應(yīng)。盡管這符合冪等性的定義,卻與實(shí)際業(yè)務(wù)邏輯不符。同樣,以訂單支付為例,首次調(diào)用由于賬戶余額不足而返回“余額不足”提示,用戶充值后再次使用相同參數(shù)發(fā)起支付請(qǐng)求,服務(wù)仍然返回“余額不足”響應(yīng),也符合冪等性的定義,但同樣不符合業(yè)務(wù)邏輯。udB28資訊網(wǎng)——每日最新資訊28at.com

因此,在實(shí)現(xiàn)冪等性方案時(shí),應(yīng)該遵循冪等性方案的目標(biāo),而不僅僅是嚴(yán)格遵循冪等性的定義。尤其是涉及寫操作的服務(wù),應(yīng)當(dāng)更關(guān)注防止重復(fù)請(qǐng)求帶來的不良副作用,例如重復(fù)扣款或退款。udB28資訊網(wǎng)——每日最新資訊28at.com

1.2 冪等性的必要性

在微服務(wù)和分布式架構(gòu)中,一個(gè)請(qǐng)求可能需要多個(gè)服務(wù)協(xié)作才能完成。在這個(gè)過程中,網(wǎng)絡(luò)抖動(dòng)、系統(tǒng)運(yùn)行異常等不確定因素使得請(qǐng)求的成功率不可能達(dá)到100%,一旦發(fā)生失敗或未知異常,最常見的處理方式就是重試,而重試必然會(huì)導(dǎo)致重復(fù)請(qǐng)求問題。udB28資訊網(wǎng)——每日最新資訊28at.com

冪等設(shè)計(jì)主要是為了處理重復(fù)請(qǐng)求而生的,好的冪等方案可以保證重復(fù)請(qǐng)求獲得預(yù)期結(jié)果,而不產(chǎn)生副作用。 在實(shí)際開發(fā)中,以下場(chǎng)景會(huì)產(chǎn)生重復(fù)請(qǐng)求:udB28資訊網(wǎng)——每日最新資訊28at.com

  • 用戶不可靠:用戶通過客戶端發(fā)起請(qǐng)求,由于手抖或有意重復(fù)點(diǎn)擊,很容易造成導(dǎo)致極短時(shí)間內(nèi)發(fā)起多次重復(fù)請(qǐng)求。
  • 網(wǎng)絡(luò)不可靠:網(wǎng)絡(luò)抖動(dòng)、網(wǎng)關(guān)內(nèi)部抖動(dòng)有可能觸發(fā)重試機(jī)制,這個(gè)在使用消息隊(duì)列投遞消息時(shí)經(jīng)常會(huì)遇到。
  • 服務(wù)不可靠:在需要保證數(shù)據(jù)一致性的場(chǎng)景中,如果調(diào)用下游服務(wù)超時(shí),在無法確認(rèn)執(zhí)行結(jié)果的情況下,常用的處理方法是重試。

在我的SpringCloud微服務(wù)專欄《使用RocketMQ實(shí)現(xiàn)分布式事務(wù)》一文中就遺留了個(gè)冪等導(dǎo)致的bug,由于消費(fèi)端沒做冪等處理,所以在整個(gè)消息鏈路中,如果broker沒有收到消費(fèi)者發(fā)送的ack響應(yīng)就會(huì)發(fā)起重試,從而產(chǎn)生數(shù)據(jù)一致性問題。udB28資訊網(wǎng)——每日最新資訊28at.com

1.3 冪等與并發(fā)的關(guān)系

在具有并發(fā)寫操作的場(chǎng)景下,通常需要考慮冪等問題。例如,當(dāng)用戶在極短時(shí)間內(nèi)多次提交表單或者使用特殊手段同時(shí)提交多個(gè)表單時(shí),這就是典型的并發(fā)場(chǎng)景,需要進(jìn)行冪等性處理。為了防止重復(fù)請(qǐng)求被執(zhí)行,服務(wù)端需要實(shí)施冪等性控制,以避免產(chǎn)生不符合預(yù)期的結(jié)果。udB28資訊網(wǎng)——每日最新資訊28at.com

雖然并發(fā)場(chǎng)景大都存在冪等問題,但冪等問題卻并非并發(fā)場(chǎng)景所特有。冪等設(shè)計(jì)是為了識(shí)別并處理重復(fù)請(qǐng)求,而并發(fā)僅僅是重復(fù)請(qǐng)求的一種特殊情況。 事實(shí)上,只要重復(fù)請(qǐng)求涉及寫操作,無論是否并發(fā),都需要做好冪等處理。舉個(gè)例子,用戶在pc端同時(shí)開了兩個(gè)窗口,間隔10分鐘分別提交表單,所有參數(shù)完全相同,這顯然不屬于并發(fā),但仍需要進(jìn)行冪等處理。udB28資訊網(wǎng)——每日最新資訊28at.com

在互聯(lián)網(wǎng)領(lǐng)域,并發(fā)處理與冪等性問題緊密相關(guān),這也導(dǎo)致了一些人認(rèn)為解決冪等性就是解決高并發(fā)的問題。udB28資訊網(wǎng)——每日最新資訊28at.com

2. 冪等號(hào)的設(shè)計(jì)

冪等性設(shè)計(jì)的目的是確保即使在多次接收相同請(qǐng)求的情況下,也只執(zhí)行一次操作,防止重復(fù)處理。要實(shí)現(xiàn)這一點(diǎn),通常需要事先約定一個(gè)具有唯一性的標(biāo)識(shí)符,如Token或業(yè)務(wù)流水號(hào),我們稱之為冪等號(hào)(Idempotency Key)。udB28資訊網(wǎng)——每日最新資訊28at.com

冪等號(hào)有三個(gè)關(guān)鍵特性:唯一性、不變性和傳遞性。udB28資訊網(wǎng)——每日最新資訊28at.com

唯一性確保每個(gè)請(qǐng)求都能被準(zhǔn)確識(shí)別,不變性保證在請(qǐng)求處理期間冪等號(hào)保持不變,傳遞性則確保在多系統(tǒng)處理同一請(qǐng)求時(shí),冪等號(hào)能夠被傳遞和保持。udB28資訊網(wǎng)——每日最新資訊28at.com

冪等號(hào)通常有兩種設(shè)計(jì)方式:udB28資訊網(wǎng)——每日最新資訊28at.com

  1. 非業(yè)務(wù)冪等號(hào):通過唯一標(biāo)識(shí)符(如UUID、時(shí)間戳或業(yè)務(wù)流水號(hào))在調(diào)用方和被調(diào)用方之間明確實(shí)現(xiàn)冪等性。由于非業(yè)務(wù)冪等號(hào)難以通過業(yè)務(wù)上下文追溯,因此調(diào)用雙方都必須將其持久化,從而保證請(qǐng)求與冪等號(hào)的關(guān)系有跡可循。例如,在DailyMart案例中,訂單服務(wù)在調(diào)用庫(kù)存服務(wù)時(shí)會(huì)傳遞訂單流水號(hào)作為冪等號(hào),以便在多次請(qǐng)求時(shí)識(shí)別重復(fù)操作。
  2. 業(yè)務(wù)冪等號(hào):由業(yè)務(wù)元素組合構(gòu)成的冪等號(hào),如“用戶ID+活動(dòng)ID”。使用此方法時(shí),調(diào)用方無需單獨(dú)持久化冪等號(hào),被調(diào)用方可以根據(jù)請(qǐng)求參數(shù)和業(yè)務(wù)上下文直接獲取并組合這些參數(shù)。例如,通過設(shè)置“用戶ID”和“活動(dòng)ID”的聯(lián)合唯一索引來實(shí)現(xiàn)冪等性。

3. 冪等的實(shí)現(xiàn)方案

冪等性的實(shí)現(xiàn)關(guān)鍵在于確保相同的請(qǐng)求僅被處理一次,這通??梢酝ㄟ^設(shè)置唯一性約束和檢查來實(shí)現(xiàn)。實(shí)踐中有六種常見的方案:唯一索引、Token機(jī)制、悲觀鎖、樂觀鎖、分布式鎖和狀態(tài)機(jī)。udB28資訊網(wǎng)——每日最新資訊28at.com

3.1 唯一索引方案機(jī)制

唯一索引方案依賴于數(shù)據(jù)庫(kù)表中不允許存在具有相同索引值的重復(fù)行。這種策略在關(guān)系型數(shù)據(jù)庫(kù)中廣泛支持,并且能有效利用唯一性約束來確保冪等性。在高并發(fā)場(chǎng)景中,唯一索引能保證當(dāng)多個(gè)線程嘗試同時(shí)插入相同記錄時(shí),只有一個(gè)線程能成功執(zhí)行,而其他線程將會(huì)因違反唯一性約束而拋出異常。udB28資訊網(wǎng)——每日最新資訊28at.com

通常,業(yè)務(wù)流水表的建立是基于以下核心字段:udB28資訊網(wǎng)——每日最新資訊28at.com

  • id(bigint 類型):作為主鍵,唯一標(biāo)識(shí)每條記錄。
  • gmt_create(datetime 類型):記錄的創(chuàng)建時(shí)間。
  • gmt_modified(datetime 類型):記錄的最后修改時(shí)間。
  • user_id(varchar(32) 類型):用戶ID,這個(gè)字段也可以作為分表的依據(jù)。
  • out_biz_no(varchar(64) 類型):外部業(yè)務(wù)流水號(hào),即調(diào)用方的冪等號(hào)。
  • biz_no(varchar(64) 類型):內(nèi)部業(yè)務(wù)流水號(hào),用于系統(tǒng)內(nèi)部追蹤。
  • status(char(1) 類型):記錄執(zhí)行狀態(tài)。

在這種設(shè)計(jì)中,user_id和out_biz_no通常會(huì)組合成一個(gè)聯(lián)合索引,這樣做能有效避免在并發(fā)情況下的數(shù)據(jù)重復(fù)插入問題,從而保障了業(yè)務(wù)操作的冪等性。udB28資訊網(wǎng)——每日最新資訊28at.com

3.2 Token機(jī)制

Token機(jī)制是用于防止客戶端重復(fù)提交的一種特殊機(jī)制,特別適用于客戶端創(chuàng)建訂單等提交表單場(chǎng)景。其執(zhí)行流程如下:udB28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片udB28資訊網(wǎng)——每日最新資訊28at.com

1)當(dāng)用戶訪問表單頁(yè)面時(shí),客戶端請(qǐng)求服務(wù)端接口以獲取唯一的Token(可以是UUID或全局ID),服務(wù)端生成的Token會(huì)被存儲(chǔ)在Redis或數(shù)據(jù)庫(kù)中。udB28資訊網(wǎng)——每日最新資訊28at.com

2)用戶首次提交表單時(shí),將Token與表單一起發(fā)送至服務(wù)端,服務(wù)端會(huì)驗(yàn)證Token的存在性,如果Token存在,則執(zhí)行業(yè)務(wù)邏輯,并在完成后銷毀Token。udB28資訊網(wǎng)——每日最新資訊28at.com

3)用戶再次提交表單時(shí),同樣攜帶Token一起發(fā)送至服務(wù)端。但由于Token已被銷毀,服務(wù)端無法找到對(duì)應(yīng)的Token,從而拒絕重復(fù)提交請(qǐng)求。udB28資訊網(wǎng)——每日最新資訊28at.com

3.3 悲觀鎖機(jī)制

悲觀鎖依賴數(shù)據(jù)庫(kù)提供的鎖機(jī)制來實(shí)現(xiàn),整個(gè)數(shù)據(jù)處理過程中,數(shù)據(jù)處于鎖定狀態(tài),并與事務(wù)機(jī)制配合,能夠有效實(shí)現(xiàn)業(yè)務(wù)冪等性。操作示例如下:udB28資訊網(wǎng)——每日最新資訊28at.com

// 1. 開啟事務(wù)begin;// 2. 基于冪等號(hào)查詢r(jià)ecord = select * from tbl_xxx where out_biz_no = 'xxx' for update;// 3. 根據(jù)狀態(tài)進(jìn)行決策if(record.getStatus() != 預(yù)期狀態(tài)){   return;}// 4. 更新記錄update tbl_xxx set status = '目標(biāo)狀態(tài)' where out_biz_no = 'xxx';// 5. 提交事務(wù)commit;

悲觀鎖主要適用于更新場(chǎng)景,通過串行化請(qǐng)求處理來確保冪等性,但需要小心使用,因?yàn)樵诓l(fā)場(chǎng)景下,重復(fù)請(qǐng)求可能會(huì)導(dǎo)致線程長(zhǎng)時(shí)間處于等待狀態(tài),浪費(fèi)資源且降低性能。udB28資訊網(wǎng)——每日最新資訊28at.com

3.4 樂觀鎖機(jī)制

樂觀鎖主要依靠"帶條件更新"(update with condition)來確保多次外部請(qǐng)求的一致性。在系統(tǒng)設(shè)計(jì)中,可以在數(shù)據(jù)表中添加版本號(hào)字段,用于標(biāo)識(shí)當(dāng)前數(shù)據(jù)的版本。每次對(duì)該數(shù)據(jù)表的記錄進(jìn)行更新時(shí),都需要提供上一次更新的版本號(hào),示例操作如下:udB28資訊網(wǎng)——每日最新資訊28at.com

//1. 取出要更新的對(duì)象,帶有版本versoinselect * from tablename where id = xxx//2. 更新數(shù)據(jù)update tableName set sq = sq-#{quantity},version = #{version}+1 where id = xxx and versinotallow=#{version}

樂觀鎖主要適用于更新場(chǎng)景,確保多次更新不會(huì)影響結(jié)果的一致性。udB28資訊網(wǎng)——每日最新資訊28at.com

3.5 分布式鎖機(jī)制

分布式鎖與悲觀鎖本質(zhì)上相似,都通過串行化請(qǐng)求處理來實(shí)現(xiàn)冪等性。與悲觀鎖不同的是,分布式鎖更輕量。在系統(tǒng)接收請(qǐng)求后,首先嘗試獲取分布式鎖。如果成功獲取鎖,則執(zhí)行業(yè)務(wù)邏輯;如果獲取失敗,則立即拒絕請(qǐng)求。udB28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片udB28資訊網(wǎng)——每日最新資訊28at.com

分布式鎖的核心是識(shí)別重復(fù)請(qǐng)求,實(shí)現(xiàn)串行化處理。但要注意,獲取鎖成功后,業(yè)務(wù)邏輯的執(zhí)行并沒有可靠保證。因此,在實(shí)際應(yīng)用中,分布式鎖需要結(jié)合事務(wù)機(jī)制和重試機(jī)制,以形成完整的冪等性解決方案。udB28資訊網(wǎng)——每日最新資訊28at.com

3.6 狀態(tài)機(jī)機(jī)制

在許多業(yè)務(wù)單據(jù)中,存在有限數(shù)量的狀態(tài),并且這些狀態(tài)之間的流轉(zhuǎn)順序是固定的。如果狀態(tài)已經(jīng)處于下一個(gè)狀態(tài),那么再次應(yīng)用上一個(gè)狀態(tài)的變更邏輯是不會(huì)產(chǎn)生任何效果的,這就確保了有限狀態(tài)機(jī)的冪等性。udB28資訊網(wǎng)——每日最新資訊28at.com

例如,庫(kù)存狀態(tài)通常包括"預(yù)扣中"、"扣減中"、"占用中"和"已釋放"等狀態(tài)。如果系統(tǒng)重復(fù)調(diào)用扣減接口,而庫(kù)存狀態(tài)已經(jīng)是"扣減中",則可以直接返回結(jié)果。udB28資訊網(wǎng)——每日最新資訊28at.com

狀態(tài)機(jī)可以與樂觀鎖機(jī)制結(jié)合使用,示例操作如下:udB28資訊網(wǎng)——每日最新資訊28at.com

update tableName set sq=sq-#{quantity},status=#{udpate_status} where id =#{id} and status=#{status}

3.7 小結(jié)

上面介紹了冪等方式的6種實(shí)現(xiàn)方案并簡(jiǎn)單介紹了每周方案的適合場(chǎng)景,這些方案的技術(shù)路線可以總結(jié)成三條:唯一索引、唯一數(shù)據(jù)、狀態(tài)機(jī)約束。udB28資訊網(wǎng)——每日最新資訊28at.com

唯一索引是指數(shù)據(jù)庫(kù)唯一索引,唯一索引大部分是基于業(yè)務(wù)流水表建立,也可單獨(dú)建表實(shí)現(xiàn);唯一數(shù)據(jù)是指悲觀鎖、樂觀鎖、分布式鎖等機(jī)制;狀態(tài)機(jī)約束,對(duì)于存在狀態(tài)流轉(zhuǎn)的業(yè)務(wù),通過狀態(tài)機(jī)的流轉(zhuǎn)約束,可以實(shí)現(xiàn)有限狀態(tài)機(jī)的冪等。udB28資訊網(wǎng)——每日最新資訊28at.com

需要注意的是:在實(shí)際開發(fā)中,這些方案單獨(dú)使用很難奏效,比如悲觀鎖、分布式鎖只是將請(qǐng)求串行化處理,對(duì)于出現(xiàn)異常后的重試并沒有什么抵御能力,需要搭配唯一索引才能形成完整的冪等方案。而在唯一索引方案中也還需要搭配事務(wù)機(jī)制才能生效。所以需要結(jié)合具體的業(yè)務(wù)場(chǎng)景靈活運(yùn)用上面的實(shí)現(xiàn)方案。udB28資訊網(wǎng)——每日最新資訊28at.com

以上介紹了六種實(shí)現(xiàn)冪等性的方式,每種方式的適用場(chǎng)景和關(guān)鍵信息。這些方式可以總結(jié)為三個(gè)技術(shù)路線:唯一索引、唯一數(shù)據(jù)和狀態(tài)機(jī)約束。udB28資訊網(wǎng)——每日最新資訊28at.com

需要注意的是,在實(shí)際開發(fā)中,單獨(dú)使用這些方式可能無法完全解決問題。例如,悲觀鎖和分布式鎖只將請(qǐng)求串行化處理,沒有處理異常后的重試,因此需要結(jié)合唯一索引來實(shí)現(xiàn)完整的冪等性解決方案。同樣,因此,在實(shí)際應(yīng)用中,需要根udB28資訊網(wǎng)——每日最新資訊28at.com

以上介紹了六種實(shí)現(xiàn)冪等性的方式,并簡(jiǎn)要介紹了每種方式適用的場(chǎng)景和關(guān)鍵信息。這些方式可以總結(jié)為三個(gè)技術(shù)路線:唯一索引、唯一數(shù)據(jù)和狀態(tài)機(jī)約束。udB28資訊網(wǎng)——每日最新資訊28at.com

  • 唯一索引指的是數(shù)據(jù)庫(kù)的唯一索引,通?;跇I(yè)務(wù)流水表創(chuàng)建,也可以單獨(dú)創(chuàng)建表來實(shí)現(xiàn)。
  • 唯一數(shù)據(jù)包括悲觀鎖、樂觀鎖、分布式鎖等機(jī)制。
  • 狀態(tài)機(jī)約束適用于具有狀態(tài)流轉(zhuǎn)的業(yè)務(wù),通過狀態(tài)機(jī)的流轉(zhuǎn)約束,可以實(shí)現(xiàn)有限狀態(tài)機(jī)的冪等性。

然而,需要注意的是,在實(shí)際開發(fā)中,單獨(dú)使用這些方法往往效果有限。 例如,悲觀鎖和分布式鎖只是將請(qǐng)求串行處理,對(duì)于異常情況的重試并沒有足夠的防御能力,因此需要結(jié)合唯一索引來實(shí)現(xiàn)完整的冪等性解決方案。同樣,唯一索引方案也需要與事務(wù)機(jī)制結(jié)合使用。因此,在實(shí)際應(yīng)用中,需要根據(jù)具體的業(yè)務(wù)場(chǎng)景靈活選擇、合理的運(yùn)用上述實(shí)現(xiàn)方法。udB28資訊網(wǎng)——每日最新資訊28at.com

4. 代碼實(shí)現(xiàn)

在Dailymart項(xiàng)目中,實(shí)現(xiàn)了除悲觀鎖以外的五種冪等方案。為了方便使用,我將分布式鎖機(jī)制和Token機(jī)制封裝在一個(gè)單獨(dú)的冪等組件dailymart-idempotent-spring-boot-starter中。udB28資訊網(wǎng)——每日最新資訊28at.com

在業(yè)務(wù)模塊中,只需在pom文件中引入依賴即可使用封裝好的冪等功能。udB28資訊網(wǎng)——每日最新資訊28at.com

<dependency> <groupId>com.jianzh5</groupId> <artifactId>dailymart-idempotent-spring-boot-starter</artifactId> <version>${project.version}</version></dependency>

冪等組件的核心是利用Spring的AOP機(jī)制實(shí)現(xiàn)。在使用時(shí),只需在需要實(shí)現(xiàn)冪等的方法上添加自定義注解@Idempotent,并指定冪等方案IdempotentTypeEnum。udB28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片udB28資訊網(wǎng)——每日最新資訊28at.com

在自定義冪等組件中,分布式鎖方案依賴于Redis。因此,在SpringBoot配置文件中需要加上Redis的相關(guān)配置,并添加一些自定義配置,如Redis key的自定義前綴以及分布式鎖key的前綴。udB28資訊網(wǎng)——每日最新資訊28at.com

spring:  data:    redis:      host: xxx.xx.xx.xx      port: 29359dailymart:  cache:    redis:      prefix: "inventory:"  idempotent:    token:      prefix: "token-"      timeout: 30000

接下來,結(jié)合具體應(yīng)用場(chǎng)景,演示在DailyMart中如何實(shí)現(xiàn)這些冪等方案。udB28資訊網(wǎng)——每日最新資訊28at.com

4.1 基于唯一索引實(shí)現(xiàn)

用戶下單時(shí)需要調(diào)用庫(kù)存預(yù)扣接口,在這種新增場(chǎng)景下,可以使用唯一索引結(jié)合事務(wù)機(jī)制實(shí)現(xiàn)冪等方案。udB28資訊網(wǎng)——每日最新資訊28at.com

1、在扣減流水表中給業(yè)務(wù)流水字段transactionId加上唯一索引。udB28資訊網(wǎng)——每日最新資訊28at.com

2、在Service層讓庫(kù)存扣減和庫(kù)存修改在同一個(gè)事務(wù)中,確保出現(xiàn)重復(fù)請(qǐng)求時(shí)事務(wù)回滾,從而保證冪等性。udB28資訊網(wǎng)——每日最新資訊28at.com

這部分代碼已在上篇文章中展示,源碼位于com/jianzh5/dailymart/module/inventory/application/service/impl/InventoryServiceImpl.java。udB28資訊網(wǎng)——每日最新資訊28at.com

4.2 基于樂觀鎖實(shí)現(xiàn)

用戶付款時(shí)會(huì)調(diào)用庫(kù)存扣減接口,這種更新場(chǎng)景可以使用樂觀鎖機(jī)制來實(shí)現(xiàn)冪等方案。在Dailymart中,有兩種實(shí)現(xiàn)方式。udB28資訊網(wǎng)——每日最新資訊28at.com

4.2.1 基于原生SQL實(shí)現(xiàn)

public interface InventoryItemMapper extends BaseMapper<InventoryItemDO> {    /**     * 基于樂觀鎖實(shí)現(xiàn)更新     * @param inventoryItemDO 庫(kù)存實(shí)體     */    @Update("UPDATE inventory_item SET sellable_quantity = #{sellableQuantity},withholding_quantity = #{withholdingQuantity}, occupy_quantity = #{occupyQuantity} ,version = #{version} + 1 , update_time = NOW() WHERE id = #{id} AND version = #{version} ")    void updateByVersion(InventoryItemDO inventoryItemDO);}

4.2.2 使用mybatis-plus提供的樂觀鎖插件

1、在DO對(duì)象中使用@Version注解對(duì)樂觀鎖字段進(jìn)行標(biāo)注。udB28資訊網(wǎng)——每日最新資訊28at.com

public class InventoryItemDO extends BaseDO {    ...    @Version    private Integer version;}

2、在mybatis-plus的配置類中添加樂觀鎖插件udB28資訊網(wǎng)——每日最新資訊28at.com

public class DailyMartDsAutoConfiguration {        /**     * 設(shè)置mybatis-plus攔截器     * 1. 分頁(yè)攔截器     * 2. 樂觀鎖攔截器     */    @Bean    public MybatisPlusInterceptor mybatisPlusInterceptor() {        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();        //分頁(yè)        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));        // 樂觀鎖        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());        return interceptor;}

這樣,當(dāng)使用inventoryItemMapper.updateById(inventoryItemDO);方法時(shí)會(huì)自動(dòng)實(shí)現(xiàn)樂觀鎖。udB28資訊網(wǎng)——每日最新資訊28at.com

4.3 基于狀態(tài)機(jī)實(shí)現(xiàn)

用戶退貨時(shí)需要調(diào)用庫(kù)存釋放接口,可以基于有限狀態(tài)機(jī)來實(shí)現(xiàn)冪等。udB28資訊網(wǎng)——每日最新資訊28at.com

@Override@Transactionalpublic void releaseInventory(Long transactionId) { ... //如果已經(jīng)是釋放狀態(tài)直接返回結(jié)果 if(inventoryRecord.getState() == InventoryRecordStateEnum.RELEASE.code()){  return; } ...}

單一的狀態(tài)機(jī)機(jī)制不能很好地保證冪等性,因此需要結(jié)合樂觀鎖機(jī)制才更有效。udB28資訊網(wǎng)——每日最新資訊28at.com

4.3 基于Token實(shí)現(xiàn)

用戶在創(chuàng)建訂單時(shí)需要調(diào)用后臺(tái)接口提交表單,像這種客戶端提交表單的操作就很適合使用token機(jī)制。udB28資訊網(wǎng)——每日最新資訊28at.com

1、在客戶端進(jìn)入頁(yè)面時(shí)調(diào)用冪等組件提供的/token方法,后端自動(dòng)生成token并存儲(chǔ)到Redis中。udB28資訊網(wǎng)——每日最新資訊28at.com

@Overridepublic String createToken() { String token = Optional.ofNullable(Strings.emptyToNull(idempotentProperties.getPrefix())).orElse(TOKEN_PREFIX_KEY) + UUID.randomUUID(); log.info("Generated Idempotency Key is: {}", token); distributedCache.put(token, "", Optional.ofNullable(idempotentProperties.getTimeout()).orElse(TOKEN_EXPIRED_TIME)); return token;}

2、在創(chuàng)建訂單接口加上自定義冪等注解,指定冪等類型為Token機(jī)制。udB28資訊網(wǎng)——每日最新資訊28at.com

@PostMapping("/api/order/create")@Idempotent( type = IdempotentTypeEnum.TOKEN, message = "訂單正在創(chuàng)建,請(qǐng)勿重復(fù)提交")public void create(@RequestBody OrderDTO orderDTO) { orderService.save(orderDTO);}

Token機(jī)制也需要結(jié)合唯一索引才能形成完整的冪等方案。udB28資訊網(wǎng)——每日最新資訊28at.com

4.3 基于分布式鎖實(shí)現(xiàn)

使用分布式鎖冪等方案很簡(jiǎn)單,在方法上加上冪等注解即可。有兩種使用方式:udB28資訊網(wǎng)——每日最新資訊28at.com

1、指定type為IdempotentTypeEnum.PARAM,此時(shí)冪等組件會(huì)將整個(gè)表單的參數(shù)做MD5摘要后作為分布式鎖的keyudB28資訊網(wǎng)——每日最新資訊28at.com

@Idempotent( type = IdempotentTypeEnum.PARAM, message = "訂單正在創(chuàng)建,請(qǐng)勿重復(fù)提交")@PostMapping("/api/order/create")  public void create(@RequestBody OrderDTO orderDTO) {      orderService.create(orderDTO);  }

2、指定type為IdempotentTypeEnum.SpEL,此時(shí)冪等組件會(huì)根據(jù)key的值選取參數(shù)作為分布式鎖的key,冪等key可以使用SpEL表達(dá)式選擇參數(shù)中的字段。udB28資訊網(wǎng)——每日最新資訊28at.com

@Idempotent(   key = "#lockRequest.transactionId",  type = IdempotentTypeEnum.SpEL  )@PostMapping("/api/order/update")  public void update(@RequestBody OrderDTO orderDTO) {      orderService.update(orderDTO);  }

通過以上實(shí)現(xiàn),Dailymart項(xiàng)目成功應(yīng)用了多種冪等性方案,確保了系統(tǒng)的可靠性和穩(wěn)定性。udB28資訊網(wǎng)——每日最新資訊28at.com

5. 小結(jié)

本文詳細(xì)介紹了在分布式系統(tǒng)中冪等性實(shí)現(xiàn)方案,同時(shí)著重講解了冪等和并發(fā)之間的區(qū)別。一般而言,并發(fā)都會(huì)伴隨冪等,而冪等又并非并發(fā)獨(dú)有。文章中提供了多種關(guān)于冪等的實(shí)現(xiàn)方案,不過需要記住,單一使用某種冪等方案往往很難奏效,需要組合多種方式才能形成完整的解決方案。udB28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-92739-0.htmlSpringBoot項(xiàng)目保證接口冪等的五種方法!

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 聊聊 Vue2 使用Vuex結(jié)合后端請(qǐng)求管理數(shù)據(jù)狀態(tài)

下一篇: Gopher的Rust第一課:第一個(gè)Rust程序

標(biāo)簽:
  • 熱門焦點(diǎn)
  • 鴻蒙OS 4.0公測(cè)機(jī)型公布:甚至連nova6都支持

    華為全新的HarmonyOS 4.0操作系統(tǒng)將于今天下午正式登場(chǎng),官方在發(fā)布會(huì)之前也已經(jīng)正式給出了可升級(jí)的機(jī)型產(chǎn)品,這意味著這些機(jī)型會(huì)率先支持升級(jí)享用。這次的HarmonyOS 4.0支持
  • 對(duì)標(biāo)蘋果的靈動(dòng)島 華為帶來實(shí)況窗功能

    繼蘋果的靈動(dòng)島之后,華為也在今天正式推出了“實(shí)況窗”功能。據(jù)今天鴻蒙OS 4.0的現(xiàn)場(chǎng)演示顯示,華為的實(shí)況窗可以更高效的展現(xiàn)出實(shí)時(shí)通知,比如鎖屏上就能看到外賣、打車、銀行
  • 一加首款折疊屏!一加Open渲染圖出爐:罕見單手可握小尺寸

    8月5日消息,此前就有爆料稱,一加首款折疊屏手機(jī)將會(huì)在第三季度上市,如今隨著時(shí)間臨近,新機(jī)的各種消息也開始浮出水面。據(jù)悉,這款新機(jī)將會(huì)被命名為&ldquo;On
  • 企業(yè)采用CRM系統(tǒng)的11個(gè)好處

    客戶關(guān)系管理(CRM)軟件可以為企業(yè)提供很多的好處,從客戶保留到提高生產(chǎn)力。  CRM軟件用于企業(yè)收集客戶互動(dòng),以改善客戶體驗(yàn)和滿意度。  CRM軟件市場(chǎng)規(guī)模如今超過580
  • 在線圖片編輯器,支持PSD解析、AI摳圖等

    自從我上次分享一個(gè)人開發(fā)仿造稿定設(shè)計(jì)的圖片編輯器到現(xiàn)在,不知不覺已過去一年時(shí)間了,期間我經(jīng)歷了裁員失業(yè)、面試找工作碰壁,寒冬下一直沒有很好地履行計(jì)劃.....這些就放在日
  • 大廠卷向扁平化

    來源:新熵作者丨南枝 編輯丨月見大廠職級(jí)不香了。俗話說,兵無常勢(shì),水無常形,互聯(lián)網(wǎng)企業(yè)調(diào)整職級(jí)體系并不稀奇。7月13日,淘寶天貓集團(tuán)啟動(dòng)了近年來最大的人力制度改革,目前已形成一
  • 微博大門常打開,迎接海外畫師漂洋東渡

    作者:互聯(lián)網(wǎng)那些事&ldquo;起猛了,我能看得懂日語(yǔ)了&rdquo;。&ldquo;為什么日本人說話我能聽懂?&rdquo;&ldquo;中文不像中文,日語(yǔ)不像日語(yǔ),但是我竟然看懂了&rdquo;&hellip;&hell
  • iQOO 11S屏幕細(xì)節(jié)公布:首發(fā)三星2K E6全感屏 安卓最好的直屏手機(jī)

    日前iQOO手機(jī)官方宣布,新一代電競(jìng)旗艦iQOO 11S將會(huì)在7月4日19:00正式與大家見面。隨著發(fā)布時(shí)間的日益臨近,官方關(guān)于該機(jī)的預(yù)熱也更加密集,截至目前已
  • 英特爾Xe-HP項(xiàng)目終止,將專注Xe-HPC/HPG系列顯卡

    據(jù)10 月 31 日消息報(bào)道,英特爾高級(jí)副總裁兼加速計(jì)算系統(tǒng)和圖形事業(yè)部總經(jīng)理 表示,Xe-HP“ Arctic Sound” 系列服務(wù)器 GPU 已經(jīng)應(yīng)用于 oneAPI devcloud 云服
Top 主站蜘蛛池模板: 鲁山县| 高淳县| 永寿县| 呼图壁县| 陆良县| 凉山| 通河县| 湘阴县| 章丘市| 芦溪县| 朔州市| 旬阳县| 彭泽县| 桂林市| 故城县| 桐梓县| 新和县| 盐亭县| 黔东| 吉木萨尔县| 桃园市| 龙海市| 盐津县| 静乐县| 成都市| 略阳县| 宕昌县| 商都县| 亳州市| 浮梁县| 东山县| 昭苏县| 武乡县| 五峰| 牙克石市| 日喀则市| 佛山市| 霍州市| 广东省| 淮南市| 彭阳县|