Spring Boot中冪等性的應用

Spring Boot 中,冪等性是實現分布式系統設計和接口調用的一個重要概念,尤其在高并發、分布式環境下,確保接口重復調用不會引發系統數據異常至關重要。

冪等性概念

冪等性(Idempotence)是指一次請求和重復多次請求對系統的影響完全相同。在接口調用中,如果一個接口滿足冪等性,那么無論調用多少次,最終結果是一樣的。

場景分析

  1. 支付系統
    防止重復支付。例如用戶多次點擊支付按鈕,導致重復扣款。
  2. 訂單創建
    防止用戶重復下單,產生多個相同訂單。
  3. 短信發送
    防止重復發送短信,避免浪費資源。
  4. 庫存扣減
    防止并發扣減庫存,導致庫存不足或超賣。
  5. 分布式任務處理
    防止任務重復執行,保證最終一致性。

如何實現冪等性

在 Spring Boot 中,常用以下幾種方法實現冪等性:

1.基于數據庫唯一約束

原理:
利用數據庫的唯一約束機制,確保同一請求只能操作一次。

實現:

  • 在數據庫表中增加一個唯一字段(如訂單號、請求 ID)。
  • 插入數據時,利用唯一約束防止重復寫入。

代碼示例:

@Entity
@Table(name = "orders", uniqueConstraints = {@UniqueConstraint(columnNames = "orderId")})
public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false)private String orderId; // 唯一訂單號@Column(nullable = false)private BigDecimal amount;}

當重復提交時,數據庫會拋出 DuplicateKeyException,可以捕獲并返回提示。

2.基于唯一 Token 實現

原理:

  • 每次請求都需要攜帶唯一的 token,服務器校驗 token 是否已使用。
  • 若已使用,則拒絕請求。

實現步驟:

1.客戶端向服務器申請唯一 token(如 UUID)。

2.在請求時攜帶 token。

3.服務端驗證 token:

  • 若 token 未使用,處理業務并標記 token 為已使用。
  • 若 token 已使用,直接返回提示。

代碼示例:

@RestController
@RequestMapping("/api/order")
public class OrderController {@Autowiredprivate StringRedisTemplate redisTemplate;@PostMapping("/create")public String createOrder(@RequestParam String token) {// 校驗 token 是否已存在Boolean isTokenExists = redisTemplate.opsForValue().setIfAbsent(token, "1", 10, TimeUnit.MINUTES);if (Boolean.FALSE.equals(isTokenExists)) {return "重復請求,請勿再次提交";}// 執行業務邏輯// ...return "訂單創建成功";}}

優點:

  • 無需修改數據庫結構。
  • 使用 Redis 提高性能,適用于高并發場景。

3.基于冪等字段校驗

原理:

  • 接口請求體中包含冪等字段(如訂單號、請求 ID)。
  • 服務端通過冪等字段判斷請求是否已處理。

實現步驟:

  • 在業務表中增加 requestId 字段,標記唯一請求。
  • 每次請求前查詢是否存在相同的 requestId。
  • 若存在,直接返回處理結果。

代碼示例:

@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;public String createOrder(String requestId, Order order) {// 校驗冪等字段if (orderRepository.existsByRequestId(requestId)) {return "訂單已創建,請勿重復提交";}// 保存訂單order.setRequestId(requestId);orderRepository.save(order);return "訂單創建成功";}}

4.基于分布式鎖

原理:

  • 利用分布式鎖(如 Redis 的 SETNX)對關鍵資源加鎖,確保同一時刻只有一個請求處理。

實現步驟:

  1. 請求時加鎖,鎖的唯一標識為冪等字段(如訂單號)。
  2. 若加鎖成功,執行業務邏輯。
  3. 業務執行完成后釋放鎖。

代碼示例:

@Service
public class SmsService {@Autowiredprivate StringRedisTemplate redisTemplate;public String sendSms(String phoneNumber) {String lockKey = "sms:lock:" + phoneNumber;// 加鎖Boolean isLockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 2, TimeUnit.MINUTES);if (Boolean.FALSE.equals(isLockAcquired)) {return "短信發送過于頻繁,請稍后再試";}try {// 執行業務邏輯// ...return "短信發送成功";} finally {// 釋放鎖redisTemplate.delete(lockKey);}}}

5.基于狀態校驗

原理:

  • 根據業務狀態判斷請求是否重復。
  • 常用于支付、庫存等有明確狀態的場景。

實現步驟:

  • 增加狀態字段(如訂單狀態、支付狀態)。
  • 請求前校驗狀態是否已完成。

代碼示例:

@Service
public class PaymentService {@Autowiredprivate OrderRepository orderRepository;public String payOrder(Long orderId) {Order order = orderRepository.findById(orderId).orElseThrow(() -> new RuntimeException("訂單不存在"));// 校驗狀態if (order.getStatus().equals("PAID")) {return "訂單已支付,請勿重復操作";}// 修改訂單狀態order.setStatus("PAID");orderRepository.save(order);return "支付成功";}}

冪等性設計注意事項

1.選擇合適的冪等方案

  • 數據庫唯一約束適合低并發場景。
  • Redis 分布式鎖適合高并發場景。
  • 冪等字段校驗適合需要記錄請求 ID 的場景。

2.冪等字段的設計

  • 冪等字段應具有唯一性,如訂單號、請求 ID。
  • 客戶端生成或服務端分配均可。

3.冪等性與事務

  • 確保冪等校驗與業務邏輯在同一事務中執行,避免校驗通過但業務未執行完成的情況。

4.性能優化

  • 使用緩存(如 Redis)提高冪等校驗性能,減少數據庫壓力。

總結

Spring Boot 中的冪等性實現,是確保接口安全性和數據一致性的關鍵。根據業務場景的不同,選擇合適的冪等方案至關重要:

  • 數據庫唯一約束:簡單場景,直接使用。
  • Redis 分布式鎖:高并發場景,提升性能。
  • 冪等字段校驗:需要記錄唯一請求的場景。

冪等性設計不僅是接口安全的保障,更是系統穩定性的核心體現。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/64028.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64028.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64028.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode 7. 整數反轉

class Solution { public: int reverse(int x) { long long n0; if(x0) return 0; while(x%100) { xx/10; } while(x!0) { nn*10x%10; xx/10; } if(n<-2147483648||n>2147483647) return 0; return n; } };

[項目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 測試及總結

目錄 編寫http_server模塊 1. 引入cpp-httplib到項目中 2. cpp-httplib的使用介紹 3. 正式編寫http_server 九、添加日志到項目中 十、編寫前端模塊 十一. 詳解傳 gitee 十二、項目總結 項目的擴展 寫在前面 [項目詳解][boost搜索引擎#1] 概述 | 去標簽 | 數據清洗 |…

xxl-job 簡單的入門到實戰

本文是參考官方文檔自己實踐一次&#xff0c;純享版&#xff0c;大致也是作者邊寫博客邊去跟著官方文檔實現 一、前期準備 1、官網地址 GitHub地址&#xff1a; GitHub - xuxueli/xxl-job: A distributed task scheduling framework.&#xff08;分布式任務調度平臺XXL-JOB&…

Centos7, 使用yum工具,出現 Could not resolve host: mirrorlist.centos.org

在 CentOS 7 中使用 yum 工具時&#xff0c;如果出現 "Could not resolve host: mirrorlist.centos.org" 的錯誤&#xff0c;通常是因為默認的鏡像源無法訪問。以下是一些常用的解決方法&#xff1a; 檢查網絡連接&#xff1a;首先使用 ping 命令測試網絡連接是否正常…

【教程】通過Docker運行AnythingLLM

轉載請注明出處&#xff1a;小鋒學長生活大爆炸[xfxuezhagn.cn] 如果本文幫助到了你&#xff0c;歡迎[點贊、收藏、關注]哦~ 官方教程&#xff1a;Local Docker Installation ~ AnythingLLM 1、先創建一個目錄用于保存anythingllm的持久化文件&#xff1a; sudo mkdir /app su…

若依(RuoYi-Vue)+Flowable工作流前后端整合教程

此教程適合若依前后端分離項目&#xff0c;其他項目可以在擴展列表中進行查找。 近期公司里需要對很久以前的RuoYi-Vue前后端分離項目擴展出flowable的功能&#xff0c;當然這個重任也是落在了我的身上&#xff08;不然也不會有這篇文章&#xff09;&#xff0c;然后我在官網看…

ubuntu 網絡管理--NetworkManager

ubuntu 網絡管理--NetworkManager 1 介紹2 NetworkManager 命令2 nmcli 命令顯示可用的wifi AP連接wifi檢查網絡連接 ?? 如何刪除刪除網絡連接查看設備狀態添加一個新的以太網連接設置靜態 IP 地址啟用并測試連接添加新的wifi連接 3 其他命令參考 1 介紹 NetworkManager 是標…

計算機網絡習題(第5章 網絡層 第6章 傳輸層)

第5章 網絡層 一、單選題 1、下列關于 IPv4 地址的說法中&#xff0c;錯誤的是( )。 A、 IP 地址是邏輯地址 B、 IP 地址一般用點分十進制表示 C、 205.106.286.36 是一個合法的 IP 地址 D、 同一個網絡中不能有兩臺計算機的 IP 地址相同 正確答案&#xff1a; C 2、…

水庫大壩三維模型的開發和使用3Dmax篇

成果圖 開發過程 工具插件three.js先加載模型做水體銜接水位測量標尺水位標記斷面標記大壩監測點打點 上代碼&#xff0c;技術交流V: bloxed <template><div class"box w100 h100"><el-row :gutter"20" v-loading"loading"e…

【藍橋杯每日一題】分糖果——DFS

分糖果 藍橋杯每日一題 2024-12-24 分糖果 DFS 題目描述 兩種糖果分別有 9 個和 16 個&#xff0c;要全部分給 7 個小朋友&#xff0c;每個小朋友得到的糖果總數最少為 2 個最多為 5 個&#xff0c;問有多少種不同的分法。糖果必須全部分完。 只要有其中一個小朋友在兩種方案中…

計算機畢設-基于springboot的校園招聘網站的設計與實現(附源碼+lw+ppt+開題報告)

博主介紹&#xff1a;?多個項目實戰經驗、多個大型網購商城開發經驗、在某機構指導學員上千名、專注于本行業領域? 技術范圍&#xff1a;Java實戰項目、Python實戰項目、微信小程序/安卓實戰項目、爬蟲大數據實戰項目、Nodejs實戰項目、PHP實戰項目、.NET實戰項目、Golang實戰…

重生之我在異世界學編程之C語言:深入動態內存管理收尾 + 柔性數組篇

大家好&#xff0c;這里是小編的博客頻道 小編的博客&#xff1a;就愛學編程 很高興在CSDN這個大家庭與大家相識&#xff0c;希望能在這里與大家共同進步&#xff0c;共同收獲更好的自己&#xff01;&#xff01;&#xff01; 本文目錄 引言正文常見的動態內存管理錯誤&#xf…

無人直播源碼

DY無人直播系統架構設計介紹 在DY等短視頻平臺的直播中&#xff0c;無人直播系統能夠提供自動化、智能化的互動體驗&#xff0c;既減輕了主播的工作量&#xff0c;又提升了觀眾的參與感。以下是一個典型的無人直播系統架構設計&#xff0c;包含全局配置、點對點互動、產品話術、…

被裁20240927 --- 嵌入式硬件開發 前篇

前篇主要介紹一些相關的概念&#xff0c;用于常識掃盲&#xff0c;后篇開始上干貨&#xff01; 他捧著一只碗吃過百家的飯 1. 處理器芯片1.1 處理器芯片制造商一、 英特爾&#xff08;Intel&#xff09;二、 三星&#xff08;SAMSUNG&#xff09;三、 高通&#xff08;Qualcomm…

準備考試:解決大學入學考試問題

引言 在編程競賽和算法挑戰中&#xff0c;我們經常會遇到各種類型的組合問題。這些問題不僅考驗我們的邏輯思維能力&#xff0c;還要求我們熟練掌握數據結構和算法。在這篇文章中&#xff0c;我們將探討一個有趣的問題——“準備考試”&#xff0c;這個問題來自于一個虛構的情…

【Linux】進程間通信 -> 匿名管道命名管道

進程間通信的目的 數據傳輸&#xff1a;一個進程許需要將它的數據發送給另外一個進程。資源共享&#xff1a;多個進程之間共享同樣的資源。通知事件&#xff1a;一個進程需要向另一個或一組進程發送消息&#xff0c;通知它們發生了某種事件&#xff08;如進程終止時要通知父進程…

Pytorch注意力機制應用到具體網絡方法(閉眼都會版)

文章目錄 以YoloV4-tiny為例要加入的注意力機制代碼模型中插入注意力機制 以YoloV4-tiny為例 解釋一下各個部分&#xff1a; 最左邊這部分為主干提取網絡&#xff0c;功能為特征提取中間這邊部分為FPN&#xff0c;功能是加強特征提取最后一部分為yolo head&#xff0c;功能為獲…

修改el-select下拉框高度;更新:支持動態修改

文章目錄 效果動態修改&#xff1a;效果代碼固定高度版本動態修改高度版本&#xff08;2024-12-25 更新&#xff1a; 支持動態修改下拉框高度&#xff09; 效果 動態修改&#xff1a;效果 代碼 固定高度版本 注意點&#xff1a; popper-class 盡量獨一無二&#xff0c;防止影…

開關電源特點、分類、工作方式

什么叫開關電源隨著電力電子技術的發展和創新&#xff0c;使得開關電源技術也在不斷地創新。目前&#xff0c;開關電源以小型、輕量和高效率的特點被廣泛應用幾乎所有的電子設備&#xff0c;是當今電子信息產業飛速發展不可缺少的一種電源方式。 開關電源是利用現代電力電子技…

Linux應用軟件編程-文件操作(目錄io)

1.打開目錄&#xff1a; DIR *opendir(const char *name); 功能&#xff1a;打開一個目錄獲得一個目錄流指針 參數: name:目錄名 返回值&#xff1a;成功返回目錄流指針&#xff1b;失敗返回NULL 2.讀目錄&#xff1a; struct dirent *readdir(DIR *dirp); 功能&…