網(wǎng)站首頁 編程語言 正文
分布式鎖應(yīng)用場(chǎng)景
秒殺環(huán)境下:訂單服務(wù)從庫存中心拿到庫存數(shù),如果庫存總數(shù)大于0,則進(jìn)行庫存扣減,并創(chuàng)建訂單
訂單服務(wù)負(fù)責(zé)創(chuàng)建訂單
庫存服務(wù)負(fù)責(zé)扣減庫存
模擬用戶訪問庫存
多線程并發(fā)訪問,出現(xiàn)超賣問題,線程不安全。沒有保證原子性
單體鎖的分類
單體應(yīng)用鎖指的是只能在 一個(gè)JVM 進(jìn)程內(nèi)有效的鎖。我們把這種鎖叫做單體應(yīng)用鎖
synchronized鎖ReentrantLock鎖
一個(gè) Tomcat 可以看作是一個(gè)JVM進(jìn)程,當(dāng)大量請(qǐng)求并發(fā)到系統(tǒng)時(shí),所有的請(qǐng)求都落在這唯一的一個(gè)Tomcat上,如果某些請(qǐng)求方法是需要加鎖的,比如:秒殺扣減庫存,是可以滿足需求的,但是隨著訪問量的增加,導(dǎo)致一個(gè)tomcat 難以支撐,這時(shí)我們必然就是集群部署Tomcat ,使用多個(gè) Tomcat 共同支撐整個(gè)系統(tǒng)。
我們看到系統(tǒng)中存在兩個(gè)Tomcat,我們加的鎖是JDK提供的鎖,這種鎖只能在 一個(gè)JVM 下起到作用,也就是在一個(gè)Tomcat內(nèi)是沒有問題的。當(dāng)存在兩個(gè)或兩個(gè)以上的Tomcat時(shí),大量的并發(fā)請(qǐng)求分散到不同的Tomcat上,在每一個(gè)Tomcat中都可以防止并發(fā)的產(chǎn)生,但是在多個(gè)Tomcat之間,每個(gè)Tomcat中獲得鎖的這個(gè)請(qǐng)求,又產(chǎn)生了并發(fā),從而產(chǎn)生超賣現(xiàn)象。這也就是單體應(yīng)用鎖的局限性了,它只能在一個(gè)JVM內(nèi)加鎖,所以單體鎖只能鎖住單體環(huán)境,是鎖不住分布式環(huán)境或集群環(huán)境的。
分布式鎖核心邏輯
分布式鎖的核心邏輯就是在多個(gè)服務(wù)中設(shè)置一個(gè)公共的資源,在公共資源中設(shè)置鎖,供多個(gè)服務(wù)去同時(shí)搶奪鎖資源,一旦其中一個(gè)線程搶奪成功,其他線程就進(jìn)入自旋狀態(tài),不同的嘗試訪問獲取鎖資源,在獲取鎖資源的線程執(zhí)行完相應(yīng)的邏輯以后就會(huì)釋放鎖資源,其他線程就可以獲取鎖資源。
分布式鎖實(shí)現(xiàn)的問題——死鎖和解決
死鎖:
如果某個(gè)線程在執(zhí)行鎖邏輯過程中宕機(jī),導(dǎo)致沒有刪除鎖
解決:
添加過期時(shí)間
因?yàn)槭欠窃有蕴砑舆^期時(shí)間,可能導(dǎo)致在添加過期時(shí)間之前就出現(xiàn)宕機(jī)現(xiàn)象,此時(shí)依舊進(jìn)入死鎖狀態(tài)。原子性添加過期時(shí)間
Redis解決刪除別人鎖的問題
刪除別人鎖:
當(dāng)有線程A進(jìn)入后由于超時(shí),有其他線程B進(jìn)入,此時(shí)redis中的鎖是線程B的,而原來的線程A接著執(zhí)行,線程A刪除了別人的鎖。
刪除別人鎖解決:
①給當(dāng)前線程綁定一個(gè)局部變量uuid,由于每個(gè)線程都有一份自己的局部變量,那么線程和局部變量綁定之后,我們?cè)趧h除鎖之前判斷一下,當(dāng)前這把鎖是不是自己的載進(jìn)行刪除
②使用lua表達(dá)式進(jìn)一步解決
上述方案還是存在問題,在線程A自己的uuid剛好與redis的uuid比較完,正準(zhǔn)備刪除的時(shí)候過期,這時(shí)候B線程進(jìn)入,此時(shí)的redisuuid就不是線程A的了,此時(shí)還是會(huì)存在刪除別人鎖的問題。
這是由于在拿鎖、比較鎖和刪除鎖的過程中并不是原子性的操作。解決此問題可以使用lua表達(dá)式
原文鏈接:https://blog.csdn.net/xiaowanziddd/article/details/125583692
相關(guān)推薦
- 2022-06-18 Elasticsearches通過坐標(biāo)位置實(shí)現(xiàn)對(duì)附近人的搜索_其它綜合
- 2022-02-25 image-webpack-loader 報(bào)錯(cuò) Invalid regular expression
- 2022-11-27 Python+decimal完成精度計(jì)算的示例詳解_python
- 2022-02-26 Hutool cn.hutool.core.bean.BeanException: Set valu
- 2023-10-12 解決父元素opacity會(huì)影響子元素的問題
- 2023-03-01 shell?sleep睡眠命令的具體使用_linux shell
- 2024-07-13 Springboot使用注解實(shí)現(xiàn)權(quán)限校驗(yàn)
- 2022-04-01 k8s 使用kubectl訪問api-server失敗,node “XXX“ not found
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支