redis實現秒殺超賣問題的解決方案:(僅限于單體項目)

秒殺實現通過樂觀鎖控制超賣問題

通過悲觀鎖控制每個用戶只能下一單,避免用戶多次點擊,發送的多次下單請求(即多個線程)都成功,避免惡意攻擊

????????????????????????每個請求訪問Tomcat時,就會分配一個線程處理請求

業務邏輯:

注*以下邏輯中報錯也可以改為給前端返回錯誤信息

1.檢查數據庫查看庫存是否>0,不滿足直接報錯

2.當數據庫庫存>0,檢查該用戶對本商品的訂單是否存在,如果已存在說明下過單,報錯

3.如果訂單也不存在,對數據庫數據進行減庫存,這里容易出現超賣,使用樂觀鎖

4.減庫存后創建訂單,這個過程和2步驟有關聯,應該使用悲觀鎖控制2-4步驟的訪問

樂觀鎖(本質sql的where語句驗證):即修改數據庫前查看數據前后是否一致,不一致說明中間有其他線程修改數據,則放棄修改。

update product set sale=slae-1 where sale=?
//?為檢查數據庫庫存是否>0時查詢的值,這樣在修改數據時通過where在驗證一遍數據是否被修改

缺點:高并發場景下修改數據庫成功率太低!

優化:寬松的樂觀鎖,嚴格來說不算樂觀鎖了,就是條件更改

update product set sale=slae-1 where sale>0

將條件變為sale>0哪怕中間有其他線程進行減庫存,只要數量依然>0依然允許修改,這樣就可以完美符合我們減庫存的預期(可以使用Jmeter工具進行高并發測試)

悲觀鎖(本質synchronized同步機制):避免同一個用戶對創建訂單接口訪問進行多次請求時,多次請求都創建訂單成功。如果不是同一用戶,允許異步訪問數據庫創建多個不同用戶訂單

1.應該將2-4步驟抽離出單獨放到一個方法里面,因為減庫存和創建訂單是一個事務,應該將其放到同一事務中執行

2.同步鎖不建議直接加到2-4步驟的方法上面,因為方法同步鎖,鎖對象都是this,如果該類中有多個鎖的對象都是this,容易照成線程的過度阻塞,導致程序反應變慢

所以對象鎖不應該綁定this而是和userID綁定,因此就要使用同步代碼塊進行上鎖,鎖對象都為和userID掛鉤的同一種對象即可-----這里使用userID.toString().intern()來指定鎖對象

2.1為什么使用userID.toString().intern()來充當鎖對象:

如果直接使用Integer類型的userID參數對象,來作為鎖對象毫無意義,因為不同請求傳遞的參數都會在堆中new出不同的對象,這樣哪怕是多個線程(請求)訪問接口,傳遞的同一userID同步鎖也無法限制他們進行同步訪問代碼塊,因為鎖對象根本不是同一對象

直接使用this也不行,因為我們只需要限制參數為同一userID的請求訪問代碼塊時要同步,不同userID的請求之間不需要使用同一把鎖限制他們。而是使用多把鎖,限制同一userID的請求進行同步訪問代碼塊2-4步驟,多把鎖允許不同userID的請求可以異步訪問訪問代碼塊2-4步驟。如果使用了this,所有請求訪問代碼塊2-4步驟時都會同步訪問,不符合我們預期

3.這個同步代碼塊不應該封裝到2-4步驟的事務方法中去,而是封裝到調用該方法的位置

如果封裝到2-4步驟的事務方法中,同一userID線程雖然訪問代碼塊被同步限制了,但是除了代碼塊后事務還沒有真正提交,這時其他同一userID的線程又進入代碼塊中,查詢數據庫中有無訂單時,可能沒有訂單,因為方法沒執行完畢,事務未提交,數據庫中還沒有訂單信息。

所以為了避免這種情況,代碼塊應該封裝到調用該事務方法的地方,將該事務方法放到代碼塊中執行

4.@Transaction事務失效

上面我們說應該在其他方法中調用2-4步驟的事務方法,但是同一類中調用事務方法,事務不會生效,只有通過spring創建的代理對象,引用事務方法時事務才會生效.

所以在引用事務方法時要通過spring框架的ApplicationContext對象的getBean(類名.class)來獲取代理對象調用事務方法,這樣事務才會生效!!

代碼實現:(僅作參考,結合業務邏輯食用)

    @AutowiredApplicationContext context;//模仿秒殺減庫存,創建訂單@Overridepublic Boolean killInSecond(Integer userID,Integer productID){//檢查庫存是否>0Product product = pm.selectByPrimaryKey(productID);if(product.getSales()<=0){throw new MyExceptionHandler("庫存不足");}//調用2-4步驟方法Boolean result=false;synchronized (userID.toString().intern()){//使用代理對象調用事務方法ProductServiceImpl bean = context.getBean(ProductServiceImpl.class);result=bean.ProductAndOrder(userID,productID);}return result;}@AutowiredOrderMapper om;@AutowiredRedisIdIncrement redisId;//redis全局唯一ID生成工具,想省事可以直接uuid//創建訂單,減庫存操作@Transactionalpublic Boolean ProductAndOrder(Integer userID,Integer productID){//檢查數據庫中書否存在該用戶訂單Integer orderCount = om.selectOrderByUserIdAndProductId(userID, productID);if(orderCount>0){throw new MyExceptionHandler("用戶已下單");}//訂單不存在減庫存,寬松樂觀鎖Integer result = pm.updateProductBysale(productID);if(result!=1){throw new MyExceptionHandler("庫存不足");}//創建訂單//獲取redis唯一IDLong orderId = redisId.getRedisID("order");//封裝訂單Order order=new Order(orderId.toString(),userID,"","",productID,"",null,1,0,null,null,null,null,new BigDecimal(100));result = om.insertCompleteOrder(order);if(result!=1){return false;}return true;}

mybatisXML文件的樂觀鎖sql語句

<!--  對單個商品減庫存--><update id="updateProductBysale">update product set sales=sales-1 where id=#{productId} and sales>0</update>

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

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

相關文章

Go與Python爬蟲實戰對比:從開發效率到性能瓶頸的深度解析

目錄 引言&#xff1a;兩種語言&#xff0c;兩種哲學 開發效率對比&#xff1a;從框架設計看易用性 Python的"開箱即用" Go的"手動組裝" 性能對比&#xff1a;從并發模型看效率差異 理論性能對比 實際測試數據 錯誤處理對比&#xff1a;從編程范式…

初識c語言————排序方法

今天我們學習的是c語言中的排序方法目錄&#xff1a;一.冒泡排序法二.選擇排序法下面我們正式學習c語言中的排序方法一.冒泡排序法1.冒泡排序法的過程&#xff1a;將無序的數組通過數組之間的大小比較&#xff0c;排成有序的樣子2.例如&#xff1a;5&#xff0c;3&#xff0c;4…

爬蟲與數據分析結合案例:中國大學排名爬取與分析全流程

爬蟲與數據分析結合案例&#xff1a;中國大學排名爬取與分析全流程 一、案例背景與目標 本案例以高三網中國大學排名&#xff08;網址&#xff1a;2021中國的大學排名一覽表_高三網&#xff09;為數據源&#xff0c;完成從數據爬取到分析可視化的全流程實踐。主要目標包括&am…

行業分享丨SimSolid 在汽車零部件開發中應用的可行性調研及實踐

*本文源自汽車行業用戶范會超投稿1、背景車型短周期開發背景下&#xff0c;高效的仿真技術顯得尤為重要。Altair 推出了多款加速設計/仿真的軟件&#xff0c;其中無網格軟件 SimSolid 與業務有一定的契合度&#xff0c;有必要論證其在汽車零部件結構分析領域的可行性。2、目標評…

MacOS字體看起來比在 Windows 上更好?

字體控們注意啦&#xff01;&#x1f389;你們有沒有發現&#xff0c;同樣一段文字&#xff0c;在Mac和Windows上看起來就是不一樣&#xff1f;Mac上的字仿佛自帶柔光濾鏡&#xff0c;圓潤又舒適&#xff1b;而Windows上的字則像是精心雕琢的刀鋒&#xff0c;銳利且清晰。這背后…

Torch -- 卷積學習day1 -- 卷積層,池化層

目錄 一、CNN概述 二、卷積層 1、卷積核 2、卷積計算 3、邊緣填充 4、步長 5、多通道卷積計算 6、多卷積核卷積計算 7、特征圖大小 8、卷積參數共享 9、局部特征提取 10、卷積層API 三、池化層 1、池化層概述 1.池化層的作用 2.池化層類型 2、池化層計算 3、步…

藍橋杯---第六屆省賽單片機組真題

先出手寫的代碼&#xff0c;代碼分析還需要一段時間&#xff0c;不難&#xff0c;大家認真寫。#include <STC15F2K60S2.H> #include "Seg.h" #include "LED.h" #include "Key.h" #include "DS1302.h" #include "DS18B20.h&…

GPT-5深度解析:精準、高效、務實的新一代AI引擎

&#x1f31f; GPT-5深度解析&#xff1a;精準、高效、務實的新一代AI引擎在萬眾矚目中&#xff0c;OpenAI于2025年8月7日正式推出GPT-5——這一代模型沒有華麗的創意革命&#xff0c;卻以驚人的準確率提升、斷崖式降價和強大的工程能力&#xff0c;悄然重塑了生成式AI的應用邊…

oss(阿里云)前端直傳

WEB端前端直傳 參考文檔&#xff1a;web前端直傳并設置上傳回調 封裝oss-upload.ts // 圖片上傳 import { uploadToken } from /api/uploadFile.js // 獲取oss token接口// 定義 OSS 信息類型 interface OssInfo {policy: string;signature: string;x_oss_credential: strin…

vscode uv 發布一個python包:編輯、調試與相對路徑導包

背景 最近一直在使用uv做python包管理&#xff0c;用起來很方便。 尤其是在代碼上傳到github的時候&#xff0c;pyproject.toml 會顯示出當前項目依賴的python包。這樣在把代碼下載到本地之后&#xff0c;直接uv sync就可以很方便地恢復出python環境。 uv 除了有上述優點&…

Secure 第四天作業

實驗需求&#xff1a;需求一拓撲&#xff1a;按照以上拓撲所示&#xff0c;完成以下需求&#xff1a;參考以上拓撲&#xff0c;配置設備IP地址&#xff0c;使用UNL里Secure第四天拓撲即可。&#xff08;有興趣的同學課后也可按照PPT原拓撲做做實驗&#xff09;&#xff1b;配置…

利用開漏輸出模式模擬IIC

/************************************************************利用IO口模擬IIC時序&#xff0c;需要使用2個IO口(SDA和SCL)SCL時鐘線只能由主器件進行控制&#xff0c;所以SCL引腳必須為輸出模式SDA數據線&#xff0c;在主器件發送數據時&#xff0c;SDA引腳為輸出模式SDA數…

閘機控制系統從設計到實現全解析:第 5 篇:RabbitMQ 消息隊列與閘機通信設計

第 5 篇&#xff1a;RabbitMQ 消息隊列與閘機通信設計RabbitMQ 是一款開源的消息隊列中間件&#xff08;Message Queue&#xff0c;MQ&#xff09;&#xff0c;基于 Erlang 語言開發&#xff0c;遵循 AMQP&#xff08;Advanced Message Queuing Protocol&#xff0c;高級消息隊…

Linux 常用命令大全:覆蓋日常 99% 操作需求

1、基本命令 pwd&#xff1a;顯示當前工作目錄的絕對路徑&#xff0c;例如在復雜目錄結構中快速確認位置&#xff0c;執行后會輸出類似/home/user/documents的結果。 cd&#xff1a;切換目錄&#xff0c;cd 目錄路徑可進入指定目錄&#xff0c;cd ~回到當前用戶的家目錄&…

普通電腦與云電腦的區別有哪些?全面科普

近年來&#xff0c;越來越多的人不再購置升級自己的電腦&#xff0c;轉而選擇云電腦&#xff0c;云端產品正在變得越來越普及易用。那么它究竟跟我們的普通本地設備有什么區別吶&#xff1f;或許很多人并不知悉&#xff0c;對此&#xff0c;本篇內容小編就為大家簡要科普一下普…

【Python】支持向量機SVM

示例代碼&#xff1a;import numpy as np import matplotlib.pyplot as plt from sklearn import svm from sklearn.datasets import make_blobs from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report# 設…

當AI學會“抄近路”:殘差網絡如何突破深度學習的極限

**——解讀《Deep Residual Learning for Image Recognition》**今天我想帶大家回到2015年&#xff0c;見證人工智能領域的一場“捷徑革命”——由何愷明等人提出的**深度殘差學習框架&#xff08;ResNet&#xff09;**。這篇論文解決了困擾AI界多年的“深度詛咒”&#xff0c;…

HCIP--BGP綜合實驗

目錄 BGP綜合實驗報告 一、實驗拓撲 二、實驗要求 三、實驗思路 &#xff08;一&#xff09;IP地址規劃 &#xff08;二&#xff09;整體思路 四、實驗步驟 &#xff08;一&#xff09; IP地址配置 &#xff08;二&#xff09; AS2內部配置OSPF協議 &#xff08;三&a…

Java 基礎編程案例:從輸入交互到邏輯處理

在Java編程學習中&#xff0c;輸入輸出、循環控制和邏輯判斷是核心基礎。本文整理了10個經典案例&#xff0c;涵蓋Scanner輸入處理、斐波那契數列、成績統計、登錄驗證等場景&#xff0c;幫助初學者掌握編程邏輯與實用技巧。 一、Scanner輸入交互&#xff1a;獲取用戶輸入并處理…

LeetCode 面試經典 150_數組/字符串_整數轉羅馬數字(18_12_C++_中等)(模擬)(對各位進行拆解)

LeetCode 面試經典 150_數組/字符串_整數轉羅馬數字&#xff08;18_12_C_中等&#xff09;題目描述&#xff1a;輸入輸出樣例&#xff1a;題解&#xff1a;解題思路&#xff1a;思路一&#xff08;模擬&#xff09;&#xff1a;思路二&#xff08;對各位進行拆解&#xff09;&a…