摘要:如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源,那么訪問(wèn)這些資源的時(shí)候,往往需要互斥來(lái)防止彼此干擾來(lái)保證一致性,在這種情況下,便需要使用到分布式鎖。基于的分布式鎖利用臨時(shí)節(jié)點(diǎn)與機(jī)制。
? ?? ?在單進(jìn)程的系統(tǒng)中,當(dāng)存在多個(gè)線程可以同時(shí)改變某個(gè)變量時(shí),就需要對(duì)變量或代碼塊做同步,使其在修改這種變量時(shí)能夠線性執(zhí)行消除并發(fā)修改變量。
? ?而同步的本質(zhì)是通過(guò)鎖來(lái)實(shí)現(xiàn)的。為了實(shí)現(xiàn)多個(gè)線程在一個(gè)時(shí)刻同一個(gè)代碼塊只能有一個(gè)線程可執(zhí)行,那么需要在某個(gè)地方做個(gè)標(biāo)記,這個(gè)標(biāo)記必須每個(gè)線程都能看到,當(dāng)標(biāo)記不存在時(shí)可以設(shè)置該標(biāo)記,其余后續(xù)線程發(fā)現(xiàn)已經(jīng)有標(biāo)記了則等待擁有標(biāo)記的線程結(jié)束同步代碼塊取消標(biāo)記后再去嘗試設(shè)置標(biāo)記。這個(gè)標(biāo)記可以理解為鎖。
? ?不同地方實(shí)現(xiàn)鎖的方式也不一樣,只要能滿足所有線程都能看得到標(biāo)記即可。如java中synchronize是在對(duì)象頭設(shè)置標(biāo)記,Lock接口的實(shí)現(xiàn)類基本上都只是某一個(gè)volitile修飾的int型變量其保證每個(gè)線程都能擁有對(duì)該int的可見(jiàn)性和原子修改,linux內(nèi)核中也是利用互斥量或信號(hào)量等內(nèi)存數(shù)據(jù)做標(biāo)記。
????分布式鎖是控制分布式系統(tǒng)之間同步訪問(wèn)共享資源的一種方式。在分布式系統(tǒng)中,常常需要協(xié)調(diào)他們的動(dòng)作。如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源,那么訪問(wèn)這些資源的時(shí)候,往往需要互斥來(lái)防止彼此干擾來(lái)保證一致性,在這種情況下,便需要使用到分布式鎖。
基于數(shù)據(jù)庫(kù)實(shí)現(xiàn)分布式鎖
基于數(shù)據(jù)庫(kù)樂(lè)觀鎖實(shí)現(xiàn):
樂(lè)觀鎖通常實(shí)現(xiàn)基于數(shù)據(jù)版本號(hào)(version)的記錄機(jī)制實(shí)現(xiàn)的,在修改數(shù)據(jù)庫(kù)前獲取版本號(hào),修改數(shù)據(jù)時(shí)與獲取版本號(hào)不一致則拋出異常(修改數(shù)據(jù)時(shí)切記對(duì)版本號(hào)進(jìn)行+1)
基于緩存(redis...)實(shí)現(xiàn)分布式鎖
使用redis的setnx()、get()、getset()方法,用于分布式鎖
setnx(lockkey, 當(dāng)前時(shí)間+過(guò)期超時(shí)時(shí)間) ,如果返回1,則獲取鎖成功;如果返回0則沒(méi)有獲取到鎖,轉(zhuǎn)向2。
get(lockkey)獲取值oldExpireTime ,并將這個(gè)value值與當(dāng)前的系統(tǒng)時(shí)間進(jìn)行比較,如果小于當(dāng)前系統(tǒng)時(shí)間,則認(rèn)為這個(gè)鎖已經(jīng)超時(shí),可以允許別的請(qǐng)求重新獲取,轉(zhuǎn)向3。
計(jì)算newExpireTime=當(dāng)前時(shí)間+過(guò)期超時(shí)時(shí)間,然后getset(lockkey, newExpireTime) 會(huì)返回當(dāng)前l(fā)ockkey的值currentExpireTime。
判斷currentExpireTime與oldExpireTime 是否相等,如果相等,說(shuō)明當(dāng)前getset設(shè)置成功,獲取到了鎖。如果不相等,說(shuō)明這個(gè)鎖又被別的請(qǐng)求獲取走了,那么當(dāng)前請(qǐng)求可以直接返回失敗,或者繼續(xù)重試。
在獲取到鎖之后,當(dāng)前線程可以開(kāi)始自己的業(yè)務(wù)處理,當(dāng)處理完畢后,比較自己的處理時(shí)間和對(duì)于鎖設(shè)置的超時(shí)時(shí)間,如果小于鎖設(shè)置的超時(shí)時(shí)間,則直接執(zhí)行delete釋放鎖;如果大于鎖設(shè)置的超時(shí)時(shí)間,則不需要再鎖進(jìn)行處理(這樣可以避免死鎖)。
基于Zookeeper的分布式鎖
????利用臨時(shí)節(jié)點(diǎn)與 watch 機(jī)制。每個(gè)鎖占用一個(gè)普通節(jié)點(diǎn) /lock,當(dāng)需要獲取鎖時(shí)在 /lock 目錄下創(chuàng)建一個(gè)臨時(shí)節(jié)點(diǎn),創(chuàng)建成功則表示獲取鎖成功,失敗則 watch/lock 節(jié)點(diǎn),有刪除操作后再去爭(zhēng)鎖。臨時(shí)節(jié)點(diǎn)好處在于當(dāng)進(jìn)程掛掉后能自動(dòng)上鎖的節(jié)點(diǎn)自動(dòng)刪除即取消鎖
????基于redisson實(shí)現(xiàn)的spring boot starter分布式鎖框架,實(shí)現(xiàn)了可重入鎖、公平鎖、聯(lián)鎖、紅鎖、讀寫(xiě)鎖等常用鎖的方式,并支持集群模式下的redis。
為什么推薦此項(xiàng)目?
我參與項(xiàng)目的開(kāi)發(fā)
高可用,使用簡(jiǎn)單
支持單機(jī)模式,集群模式,云托管模式,哨兵模式
支持參數(shù)加鎖,對(duì)象屬性上加鎖,支持方法上加鎖
引入maven依賴即可使用
io.gitee.tooleek lock-spring-boot-starter 1.1.0
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/75904.html
摘要:比如需要用多線程或分布式集群統(tǒng)計(jì)一堆用戶的相關(guān)統(tǒng)計(jì)值,由于用戶的統(tǒng)計(jì)值是共享數(shù)據(jù),因此需要保證線程安全。如果類是無(wú)狀態(tài)的,那它永遠(yuǎn)是線程安全的。參考探索并發(fā)編程二寫(xiě)線程安全的代碼 線程安全類 保證類線程安全的措施: 不共享線程間的變量; 設(shè)置屬性變量為不可變變量; 每個(gè)共享的可變變量都使用一個(gè)確定的鎖保護(hù); 保證線程安全的思路: 1. 通過(guò)架構(gòu)設(shè)計(jì) 通過(guò)上層的架構(gòu)設(shè)計(jì)和業(yè)務(wù)分析來(lái)避...
摘要:緩存穿透場(chǎng)景當(dāng)通過(guò)一個(gè)去數(shù)據(jù)庫(kù)查詢出來(lái)的數(shù)據(jù)結(jié)果為緩存系統(tǒng)就不會(huì)緩存該數(shù)據(jù)每次該查詢都會(huì)經(jīng)過(guò)數(shù)據(jù)庫(kù)層造成沒(méi)有必要的開(kāi)銷解決方案將該緩存至緩存系統(tǒng)中為一個(gè)特殊值緩存失效場(chǎng)景由于初始化的時(shí)候某些緩存過(guò)期時(shí)間設(shè)置的都一樣一段時(shí)間以后緩存全部失效在 緩存穿透 場(chǎng)景:當(dāng)通過(guò)一個(gè)key去數(shù)據(jù)庫(kù)查詢出來(lái)的數(shù)據(jù)結(jié)果為null,緩存系統(tǒng)就不會(huì)緩存該數(shù)據(jù),每次該key查詢都會(huì)經(jīng)過(guò)數(shù)據(jù)庫(kù)層,造成沒(méi)有必要的D...
摘要:緩存穿透場(chǎng)景當(dāng)通過(guò)一個(gè)去數(shù)據(jù)庫(kù)查詢出來(lái)的數(shù)據(jù)結(jié)果為緩存系統(tǒng)就不會(huì)緩存該數(shù)據(jù)每次該查詢都會(huì)經(jīng)過(guò)數(shù)據(jù)庫(kù)層造成沒(méi)有必要的開(kāi)銷解決方案將該緩存至緩存系統(tǒng)中為一個(gè)特殊值緩存失效場(chǎng)景由于初始化的時(shí)候某些緩存過(guò)期時(shí)間設(shè)置的都一樣一段時(shí)間以后緩存全部失效在 緩存穿透 場(chǎng)景:當(dāng)通過(guò)一個(gè)key去數(shù)據(jù)庫(kù)查詢出來(lái)的數(shù)據(jù)結(jié)果為null,緩存系統(tǒng)就不會(huì)緩存該數(shù)據(jù),每次該key查詢都會(huì)經(jīng)過(guò)數(shù)據(jù)庫(kù)層,造成沒(méi)有必要的D...
摘要:緩存穿透場(chǎng)景當(dāng)通過(guò)一個(gè)去數(shù)據(jù)庫(kù)查詢出來(lái)的數(shù)據(jù)結(jié)果為緩存系統(tǒng)就不會(huì)緩存該數(shù)據(jù)每次該查詢都會(huì)經(jīng)過(guò)數(shù)據(jù)庫(kù)層造成沒(méi)有必要的開(kāi)銷解決方案將該緩存至緩存系統(tǒng)中為一個(gè)特殊值緩存失效場(chǎng)景由于初始化的時(shí)候某些緩存過(guò)期時(shí)間設(shè)置的都一樣一段時(shí)間以后緩存全部失效在 緩存穿透 場(chǎng)景:當(dāng)通過(guò)一個(gè)key去數(shù)據(jù)庫(kù)查詢出來(lái)的數(shù)據(jù)結(jié)果為null,緩存系統(tǒng)就不會(huì)緩存該數(shù)據(jù),每次該key查詢都會(huì)經(jīng)過(guò)數(shù)據(jù)庫(kù)層,造成沒(méi)有必要的D...
閱讀 3869·2023-04-26 00:36
閱讀 2676·2021-11-16 11:44
閱讀 1102·2021-11-15 17:58
閱讀 1674·2021-09-30 09:47
閱讀 1216·2019-08-30 13:05
閱讀 1550·2019-08-30 12:55
閱讀 2417·2019-08-30 11:02
閱讀 2739·2019-08-29 17:01