

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、java課程設(shè)計(jì)歷記事本代碼,已開源1.為什么要使分布式鎖使分布式鎖的的,外乎就是保證同時(shí)間只有個(gè)客戶端可以對(duì)共享資源進(jìn)操作。舉個(gè)很長(zhǎng)的例系統(tǒng) A 是個(gè)電商系統(tǒng),前是臺(tái)機(jī)器部署,系統(tǒng)中有個(gè)戶下訂單的接,但是戶下訂單之前定要去檢查下庫(kù)存,確保庫(kù)存夠了才會(huì)給戶下單。由于系統(tǒng)有定的并發(fā),所以會(huì)預(yù)先將商品的庫(kù)存保存在 Redis 中,戶下單的時(shí)候會(huì)更新 Redis 的庫(kù)存。此時(shí)系統(tǒng)架構(gòu)如下:但是這樣來(lái)會(huì)產(chǎn)個(gè)問題:假如某個(gè)時(shí)刻,Redis 的某個(gè)商品庫(kù)存為 1。此時(shí)兩個(gè)請(qǐng)求同時(shí)到來(lái),其中個(gè)請(qǐng)求執(zhí)到上圖的第 3 步,更新數(shù)據(jù)庫(kù)的庫(kù)存為 0,但是第 4 步還沒有執(zhí)。另外個(gè)請(qǐng)求執(zhí)到了第 2 步,發(fā)現(xiàn)庫(kù)存還是
2、1,就繼續(xù)執(zhí)第 3 步。這樣的結(jié)果,是導(dǎo)致賣出了 2 個(gè)商品,然其實(shí)庫(kù)存只有 1 個(gè)。很明顯不對(duì)啊!這就是典型的庫(kù)存超賣問題。此時(shí),我們很容易想到解決案:鎖把 2、3、4 步鎖住,讓他們執(zhí)完之后,另個(gè)線程才能進(jìn)來(lái)執(zhí)第 2 步。按照上的圖,在執(zhí)第 2 步時(shí),使 Java 提供的 Synchronized 或者 ReentrantLock 來(lái)鎖住,然后在第 4 步執(zhí)完之后才釋放鎖。這樣來(lái),2、3、4 這 3 個(gè)步驟就被“鎖”住了,多個(gè)線程之間只能串化執(zhí)。當(dāng)整個(gè)系統(tǒng)的并發(fā)飆升,臺(tái)機(jī)器扛不住了?,F(xiàn)在要增加臺(tái)機(jī)器,如下圖:增加機(jī)器之后,系統(tǒng)變成上圖所,假設(shè)此時(shí)兩個(gè)戶的請(qǐng)求同時(shí)到來(lái),但是落在了不同的機(jī)器上
3、,那么這兩個(gè)請(qǐng)求是可以同時(shí)執(zhí)了,還是會(huì)出現(xiàn)庫(kù)存超賣的問題。因?yàn)樯蠄D中的兩個(gè) A 系統(tǒng),運(yùn)在兩個(gè)不同的 JVM ,他們加的鎖只對(duì)屬于 JVM 的線程有效,對(duì)于其他 JVM 的線程是效的。因此,這的問題是:Java 提供的原鎖機(jī)制在多機(jī)部署場(chǎng)景下失效了,這是因?yàn)閮膳_(tái)機(jī)器加的鎖不是同個(gè)鎖(兩個(gè)鎖在不同的 JVM)。那么,我們只要保證兩臺(tái)機(jī)器加的鎖是同個(gè)鎖,問題不就解決了嗎?此時(shí),就該分布式鎖隆重登場(chǎng)了。分布式鎖的思路是:在整個(gè)系統(tǒng)提供個(gè)全局、唯的獲取鎖的“東西”,然后每個(gè)系統(tǒng)在需要加鎖時(shí),都去問這個(gè)“東西”拿到把鎖,這樣不同的系統(tǒng)拿到的就可以認(rèn)為是同把鎖。于這個(gè)“東西”,可以是 Redis、Zook
4、eeper,也可以是數(shù)據(jù)庫(kù)。此時(shí)的架構(gòu)如圖:通過上的分析,我們知道了庫(kù)存超賣場(chǎng)景在分布式部署系統(tǒng)的情況下使 Java 原的鎖機(jī)制法保證線程安全,所以我們需要到分布式鎖的案。2.效的分布式鎖在設(shè)計(jì)分布式鎖的時(shí)候,應(yīng)該考慮分布式鎖少要滿的些條件,同時(shí)考慮如何效的設(shè)計(jì)分布式鎖,以下點(diǎn)是必須要考慮的:(1) 互斥在分布式并發(fā)的條件下,最需要保證在同時(shí)刻只能有個(gè)線程獲得鎖,這是最基本的點(diǎn)。(2) 防死鎖在分布式并發(fā)的條件下,如有個(gè)線程獲得鎖的同時(shí),還沒有來(lái)得及去釋放鎖,就因?yàn)橄到y(tǒng)故障或者其它原因使它法執(zhí)釋放鎖的命令,導(dǎo)致其它線程都法獲得鎖,造成死鎖。所以分布式常有必要設(shè)置鎖的有效時(shí)間,確保系統(tǒng)出現(xiàn)故障后
5、,在定時(shí)間內(nèi)能夠主動(dòng)去釋放鎖,避免造成死鎖的情況。(3) 性能對(duì)于訪問量的共享資源,需要考慮減少鎖等待的時(shí)間,避免導(dǎo)致量線程阻塞。所以在鎖的設(shè)計(jì)時(shí),需要考慮兩點(diǎn)。1、 鎖的顆粒度要盡量。如你要通過鎖來(lái)減庫(kù)存,那這個(gè)鎖的名稱你可以設(shè)置成是商品的ID,不是任取名稱。這樣這個(gè)鎖只對(duì)當(dāng)前商品有效,鎖的顆粒度。2、 鎖的范圍盡量要。如只要鎖2代碼就可以解決問題的,那就不要去鎖10代碼了。(4) 重我們知道ReentrantLock是可重鎖,那它的特點(diǎn)就是:同個(gè)線程可以重復(fù)拿到同個(gè)資源的鎖。重鎖常有利于資源的效利。關(guān)于這點(diǎn)之后會(huì)做演。3.基于Redis實(shí)現(xiàn)分布式鎖3.1 使Redis命令實(shí)現(xiàn)分布式鎖加鎖加
6、鎖實(shí)際上就是在redis中,給Key鍵設(shè)置個(gè)值,為避免死鎖,并給定個(gè)過期時(shí)間。使的命令*:SET lock_key random_value NX PX 5000*值得注意的是:random_value 是客戶端成的唯的字符串。NX 代表只在鍵不存在時(shí),才對(duì)鍵進(jìn)設(shè)置操作。PX 5000 設(shè)置鍵的過期時(shí)間為5000毫秒。也可以使另外條命令:SETNX key value只不過過期時(shí)間法設(shè)置。這樣,如果上的命令執(zhí)成功,則證明客戶端獲取到了鎖。解鎖解鎖的過程就是將Key鍵刪除,但要保證安全性,舉個(gè)例:客戶端1的請(qǐng)求不能將客戶端2的鎖給刪除掉。釋放鎖涉及到兩條指令,這兩條指令不是原性的,需要到redi
7、s的lua腳本持特性,redis執(zhí)lua腳本是原性的。腳本如下:這種式較簡(jiǎn)單,但是也有個(gè)最重要的問題:鎖不具有可重性。使Redisson實(shí)現(xiàn)分布式鎖3.2.1Redisson介紹Redisson是架設(shè)在Redis基礎(chǔ)上的個(gè)Java駐內(nèi)存數(shù)據(jù)格(In-Memory Data Grid)。充分的利了Redis鍵值數(shù)據(jù)庫(kù)提供的系列優(yōu)勢(shì),基于Java實(shí)具包中常接,為使者提供了系列具有分布式特性的常具類。使得原本作為協(xié)調(diào)單機(jī)多線程并發(fā)程序的具包獲得了協(xié)調(diào)分布式多機(jī)多線程并發(fā)系統(tǒng)的能,降低了設(shè)計(jì)和研發(fā)規(guī)模分布式系統(tǒng)的難度。同時(shí)結(jié)合各富特的分布式服務(wù),更進(jìn)步簡(jiǎn)化了分布式環(huán)境中程序相互之間的協(xié)作。3.2.2R
8、edisson簡(jiǎn)單使Config config = new Config();config.useClusterServers()lock.unlock();只需要通過它的 API中的 Lock 和 Unlock 即可完成分布式鎖,且考慮了很多細(xì)節(jié):l Redisson 所有指令都通過 Lua 腳本執(zhí),Redis 持 Lua 腳本原性執(zhí)。l Redisson 設(shè)置個(gè) Key 的默認(rèn)過期時(shí)間為 30s,但是如果獲取鎖之后,會(huì)有個(gè)WatchDog每隔10s將key的超時(shí)時(shí)間設(shè)置為30s。另外,Redisson 還提供了對(duì) Redlock 算法的持,它的法也很簡(jiǎn)單:multiLock.unlock(
9、);3.2.3Redisson原理分析(1) 線程去獲取鎖,獲取成功:執(zhí)lua腳本,保存數(shù)據(jù)到redis數(shù)據(jù)庫(kù)。線程去獲取鎖,獲取失敗:直通過while循環(huán)嘗試獲取鎖,獲取成功后,執(zhí)lua腳本,保存數(shù)據(jù)到redis數(shù)據(jù)庫(kù)。(2) 在個(gè)分布式環(huán)境下,假如個(gè)線程獲得鎖后,突然服務(wù)器宕機(jī)了,那么這個(gè)時(shí)候在定時(shí)間后這個(gè)鎖會(huì)動(dòng)釋放,也可以設(shè)置鎖的有效時(shí)間(不設(shè)置默認(rèn)30秒),這樣的的主要是防死鎖的發(fā)。但是在實(shí)際情況中會(huì)有種情況,業(yè)務(wù)處理的時(shí)間可能會(huì)于鎖過期的時(shí)間,這樣就可能*導(dǎo)致解鎖和加鎖不是同個(gè)線程。*所以WatchDog作就是Redisson實(shí)例關(guān)閉前,不斷延長(zhǎng)鎖的有效期。如果程序調(diào)加鎖法顯式地給了
10、有效期,是不會(huì)開啟后臺(tái)線程(也就是watch dog)進(jìn)延期的,如果沒有給有效期或者給的是-1,redisson會(huì)默認(rèn)設(shè)置30s有效期并且會(huì)開啟后臺(tái)線程(watch dog)進(jìn)延期多久進(jìn)次延期:(默認(rèn)有效期/3),默認(rèn)有效期可以設(shè)置修改的,即默認(rèn)情況下每隔10s設(shè)置有效期為30s(3) Redisson可以實(shí)現(xiàn)可重加鎖機(jī)制的原因:l Redis存儲(chǔ)鎖的數(shù)據(jù)類型是Hash類型l Hash數(shù)據(jù)類型的key值包含了當(dāng)前線程的信息下是redis存儲(chǔ)的數(shù)據(jù)這表數(shù)據(jù)類型是Hash類型,Hash類型相當(dāng)于我們java的 key, 類型,這key是指 redisson它的有效期還有9秒,我們?cè)賮?lái)看們的key1
11、值為078e44a3-5f95-4e24-b6aa-80684655a15a:45它的組成是:guid + 當(dāng)前線程的ID。后的value是就和可重加鎖有關(guān)。value代表同客戶端調(diào)lock法的次數(shù),即可重計(jì)數(shù)統(tǒng)計(jì)。舉圖說(shuō)明上這圖的意思就是可重鎖的機(jī)制,它最的優(yōu)點(diǎn)就是相同線程不需要在等待鎖,是可以直接進(jìn)相應(yīng)操作。3.2.4獲取鎖的流程其中的指定字段也就是hash結(jié)構(gòu)中的field值(構(gòu)成是uuid+線程id),即判斷鎖是否是當(dāng)前線程3.2.5加鎖的流程4. 使Redis做分布式鎖的缺點(diǎn)Redis有三種部署式l 單機(jī)模式l Master-Slave+Sentienl選舉模式l Redis Clu
12、ster模式如果采單機(jī)部署模式,會(huì)存在單點(diǎn)問題,只要 Redis 故障了。加鎖就不了采 Master-Slave 模式,加鎖的時(shí)候只對(duì)個(gè)節(jié)點(diǎn)加鎖,即便通過 Sentinel 做了可,但是如果 Master 節(jié)點(diǎn)故障了,發(fā)主從切換,此時(shí)就會(huì)有可能出現(xiàn)鎖丟失的問題。基于以上的考慮,Redis 的作者也考慮到這個(gè)問題,他提出了個(gè) RedLock 的算法。這個(gè)算法的意思概是這樣的:假設(shè) Redis 的部署模式是 Redis Cluster,總共有 5 個(gè) Master 節(jié)點(diǎn)。通過以下步驟獲取把鎖:獲取當(dāng)前時(shí)間戳,單位是毫秒。輪流嘗試在每個(gè) Master 節(jié)點(diǎn)上創(chuàng)建鎖,過期時(shí)間設(shè)置較短,般就毫秒。嘗試在
13、多數(shù)節(jié)點(diǎn)上建個(gè)鎖,如 5 個(gè)節(jié)點(diǎn)就要求是 3 個(gè)節(jié)點(diǎn)(n / 2 +1)??蛻舳擞?jì)算建好鎖的時(shí)間,如果建鎖的時(shí)間于超時(shí)時(shí)間,就算建成功了。要是鎖建失敗了,那么就依次刪除這個(gè)鎖。只要?jiǎng)e建了把分布式鎖,你就得不斷輪詢?nèi)L試獲取鎖。但是這樣的這種算法,可能會(huì)出現(xiàn)節(jié)點(diǎn)崩潰重啟,多個(gè)客戶端持有鎖等其他問題,法保證加鎖的過程定正確。例如:假設(shè)共有5個(gè)Redis節(jié)點(diǎn):A,B,C,D,E。設(shè)想發(fā)了如下的事件序列:(1)客戶端1成功鎖住了A,B,C,獲取鎖成功(但D和E沒有鎖?。?2)節(jié)點(diǎn)C崩潰重啟了,但客戶端1在C上加的鎖沒有持久化下來(lái),丟失了。(3)節(jié)點(diǎn)C重啟后,客戶端2鎖住了C,D,E,獲取鎖成功。這樣,客戶端1和客戶端2同時(shí)獲得了鎖(針對(duì)同資源)。最后由于細(xì)節(jié)內(nèi)容實(shí)在太多了,為了不影響章的觀賞性,只截出了部分知識(shí)點(diǎn)致的介紹下,每個(gè)節(jié)點(diǎn)都有更細(xì)化的內(nèi)容!需要這份檔的朋友可以幫忙點(diǎn)個(gè)贊
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 萬(wàn)達(dá)城住宅臨時(shí)用電施工方案
- 2024年廣告設(shè)計(jì)制作合同
- 新學(xué)期校長(zhǎng)發(fā)言稿小學(xué)
- 餐飲業(yè)務(wù)營(yíng)收統(tǒng)計(jì)表
- 文印服務(wù)協(xié)議合同
- 2024-2025學(xué)年青海省部分學(xué)校高一上學(xué)期12月考試地理試卷(解析版)
- 產(chǎn)品發(fā)布跟蹤表-新品發(fā)布時(shí)間表
- 三農(nóng)項(xiàng)目實(shí)施步驟作業(yè)指導(dǎo)書
- 項(xiàng)目進(jìn)度跟蹤表-項(xiàng)目進(jìn)度管理與時(shí)間線
- 初中學(xué)生發(fā)言稿
- 工程施工人員安全教育培訓(xùn)【共55張課件】
- 新人教小學(xué)五年級(jí)數(shù)學(xué)下冊(cè)《怎樣通知最快》示范教學(xué)課件
- 《管理會(huì)計(jì)》說(shuō)課及試講
- 遺傳咨詢行業(yè)研究報(bào)告
- TCWAN 0112-2024 不銹鋼復(fù)合鋼板焊材匹配標(biāo)準(zhǔn)
- 新聞采訪與寫作-馬工程-第二章
- (高清版)JTG 3363-2019 公路橋涵地基與基礎(chǔ)設(shè)計(jì)規(guī)范
- 周志華-機(jī)器學(xué)習(xí)-Chap01緒論-課件
- 中石油加油站管理標(biāo)準(zhǔn)規(guī)范管理部分
- 高中雷雨完整省公開課金獎(jiǎng)全國(guó)賽課一等獎(jiǎng)微課獲獎(jiǎng)?wù)n件
- 施工現(xiàn)場(chǎng)安全標(biāo)準(zhǔn)化施工手冊(cè)(匯編)
評(píng)論
0/150
提交評(píng)論