Spring Boot接口冪等插件用法示例解析
冪等概述
冪等性原本是數(shù)學(xué)上的概念,即使公式:f(x)=f(f(x)) 能夠成立的數(shù)學(xué)性質(zhì)。用在編程領(lǐng)域,則意為對(duì)同一個(gè)系統(tǒng),使用同樣的條件,一次請(qǐng)求和重復(fù)的多次請(qǐng)求對(duì)系統(tǒng)資源的影響是一致的。
冪等性是分布式系統(tǒng)設(shè)計(jì)中十分重要的概念,具有這一性質(zhì)的接口在設(shè)計(jì)時(shí)總是秉持這樣的一種理念:調(diào)用接口發(fā)生異常并且重復(fù)嘗試時(shí),總是會(huì)造成系統(tǒng)所無法承受的損失,所以必須阻止這種現(xiàn)象的發(fā)生。
實(shí)現(xiàn)冪等的方式很多,目前基于請(qǐng)求令牌機(jī)制適用范圍較廣。其核心思想是為每一次操作生成一個(gè)唯一性的憑證,也就是 token。一個(gè) token 在操作的每一個(gè)階段只有一次執(zhí)行權(quán),一旦執(zhí)行成功則保存執(zhí)行結(jié)果。對(duì)重復(fù)的請(qǐng)求,返回同一個(gè)結(jié)果(報(bào)錯(cuò))等。參考《冪等性淺談》
冪等處理實(shí)現(xiàn)加入依賴
配置 Redis
鏈接默認(rèn)情況下,可以不配置。理論是支持 redisson-spring-boot-starter 全部配置
spring: redis: host: 127.0.0.1 port: 6379
接口
@Idempotent(key = "#key", expireTime = 10, info = "請(qǐng)勿重復(fù)查詢")
@GetMapping("/test")
public String test(String key) {
return "success";
}
測(cè)試10 個(gè)獨(dú)立線程請(qǐng)求

執(zhí)行查看結(jié)果,10 個(gè)請(qǐng)求只會(huì)有一個(gè)成功

查看后臺(tái)異常報(bào)錯(cuò),9 個(gè)異常報(bào)錯(cuò)滿足預(yù)期

idempotent 注解說明
- key: 冪等操作的唯一標(biāo)識(shí),使用 spring el 表達(dá)式 用#來引用方法參數(shù) 。 可為空則取當(dāng)前 url + args 做請(qǐng)求的唯一標(biāo)識(shí)
- expireTime: 有效期 默認(rèn):1 有效期要大于程序執(zhí)行時(shí)間,否則請(qǐng)求還是可能會(huì)進(jìn)來
- timeUnit: 時(shí)間單位 默認(rèn):s (秒)
- info: 冪等失敗提示信息,可自定義
- delKey: 是否在業(yè)務(wù)完成后刪除 key true:刪除 false:不刪除
冪等處理設(shè)計(jì)原理
1.請(qǐng)求開始前,根據(jù) key 查詢 查到結(jié)果:報(bào)錯(cuò) 未查到結(jié)果:存入 key-value-expireTime key=ip+url+args
2.請(qǐng)求結(jié)束后,直接刪除 key 不管 key 是否存在,直接刪除 是否刪除,可配置
3.expireTime 過期時(shí)間,防止一個(gè)請(qǐng)求卡死,會(huì)一直阻塞,超過過期時(shí)間,自動(dòng)刪除 過期時(shí)間要大于業(yè)務(wù)執(zhí)行時(shí)間,需要大概評(píng)估下;
4.此方案直接切的是接口請(qǐng)求層面。
5.過期時(shí)間需要大于業(yè)務(wù)執(zhí)行時(shí)間,否則業(yè)務(wù)請(qǐng)求 1 進(jìn)來還在執(zhí)行中,前端未做遮罩,或者用戶跳轉(zhuǎn)頁面后再回來做重復(fù)請(qǐng)求 2,在業(yè)務(wù)層面上看,結(jié)果依舊是不符合預(yù)期的。
6.建議 delKey = false。即使業(yè)務(wù)執(zhí)行完,也不刪除 key,強(qiáng)制鎖 expireTime 的時(shí)間。預(yù)防 5 的情況發(fā)生。
7.實(shí)現(xiàn)思路:同一個(gè)請(qǐng)求 ip 和接口,相同參數(shù)的請(qǐng)求,在 expireTime 內(nèi)多次請(qǐng)求,只允許成功一次。
8.頁面做遮罩,數(shù)據(jù)庫層面的唯一索引,先查詢?cè)偬砑?,等處理方式?yīng)該都處理下。
9.此注解只用于冪等,不用于鎖,100 個(gè)并發(fā)這種壓測(cè),會(huì)出現(xiàn)問題,在這種場(chǎng)景下也沒有意義,實(shí)際中用戶也不會(huì)出現(xiàn) 1s 或者 3s 內(nèi)手動(dòng)發(fā)送了 50 個(gè)或者 100 個(gè)重復(fù)請(qǐng)求,或者弱網(wǎng)下有 100 個(gè)重復(fù)請(qǐng)求;
總結(jié)
pig-mesh/idempotent-spring-boot-starter
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
最新hadoop安裝教程及hadoop的命令使用(親測(cè)可用)
這篇文章主要介紹了最新hadoop安裝教程(親測(cè)可用),本文主要講解了如何安裝hadoop、使用hadoop的命令及遇到的問題解決,需要的朋友可以參考下2022-06-06
Java 為什么要避免使用finalizer和Cleaner
這篇文章主要介紹了Java 為什么要避免使用finalizer和Cleaner,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-03-03
解決springboot+activemq啟動(dòng)報(bào)注解錯(cuò)誤的問題
這篇文章主要介紹了解決springboot+activemq啟動(dòng)報(bào)注解錯(cuò)誤的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
詳解springboot+atomikos+druid?數(shù)據(jù)庫連接失效分析
本文主要介紹了springboot+atomikos+druid?數(shù)據(jù)庫連接失效分析,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
文件上傳SpringBoot后端MultipartFile參數(shù)報(bào)空問題的解決辦法
這篇文章主要介紹了文件上傳SpringBoot后端MultipartFile參數(shù)報(bào)空問題的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Elasticsearch?Recovery索引分片分配詳解
這篇文章主要為大家介紹了關(guān)于Elasticsearch的Recovery索引分片分配詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2022-04-04
簡(jiǎn)單聊聊工作中常用的Java?Lambda表達(dá)式
日常開發(fā)中,我們很多時(shí)候需要用到Java?8的Lambda表達(dá)式,它允許把函數(shù)作為一個(gè)方法的參數(shù),讓我們的代碼更優(yōu)雅、更簡(jiǎn)潔。所以整理了一波工作中常用的Lambda表達(dá)式??赐暌欢〞?huì)有幫助的2022-11-11

