您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么用Redis鎖”,在日常操作中,相信很多人在怎么用Redis鎖問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么用Redis鎖”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習吧!
常用的即 synchronize 或 Lock 等 JDK 自帶的鎖,只能鎖住當前進程,僅適用于單體架構(gòu)服務(wù)。 而在分布式多服務(wù)實例場景下必須使用分布式鎖
2.1 分布式鎖的原理
廁所占坑理論
可同時去一個地方“占坑”:
占到,就執(zhí)行邏輯
否則等待,直到釋放鎖
可通過自旋方式自旋
“占坑”可以去Redis、DB、任何所有服務(wù)都能訪問的地方。
2.2 分布式鎖演進
一階段
// 占分布式鎖,去redis占坑 Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "111"); if(lock) { //加鎖成功... 執(zhí)行業(yè)務(wù) Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); redisTemplate . delete( key: "lock");//fH?ti return dataF romDb ; } else { // 加鎖失敗,重試。synchronized() // 休眠100ms重試 // 自旋 return getCatalogJsonFromDbwithRedisLock(); } 關(guān)注公眾號:麒麟改bug,可獲取Redis實戰(zhàn)學(xué)習筆記一份。
問題場景
setnx占好了坑,但是業(yè)務(wù)代碼異?;虺绦蛟趫?zhí)行過程中宕機,即沒有執(zhí)行成功刪除鎖邏輯,導(dǎo)致死鎖
解決方案:設(shè)置鎖的自動過期,即使沒有刪除,會自動刪除。
階段二
// 1. 占分布式鎖,去redis占坑 Boolean lock = redisTemplate.opsForValue().setIfAbsent( "lock", "110") if(lock) { // 加鎖成功...執(zhí)行業(yè)務(wù) // 突然斷電 // 2. 設(shè)置過期時間 redisTemplate.expire("lock", timeout: 30, TimeUnit.SECONDS) ; Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); //刪除鎖 redisTemplate. delete( key; "lock"); return dataFromDb; } else { // 加鎖失敗...重試。 synchronized () // 休眠100ms重試 // 自旋的方式 return getCatalogJsonF romDbWithRedisLock(); }
問題場景
setnx設(shè)置好,正要去設(shè)置過期時間,宕機,又死鎖
解決方案:設(shè)置過期時間和占位必須是原子操作。redis支持使用setNxEx命令
階段三
// 1. 分布式鎖占坑 Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "110", 300, TimeUnit.SECONDS); if(lock)( // 加鎖成功,執(zhí)行業(yè)務(wù) // 2. 設(shè)置過期時間,必須和加鎖一起作為原子性操作 // redisTemplate. expire( "lock", з0, TimeUnit.SECONDS); Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); // 刪除鎖 redisTemplate.delete( key: "lock") return dataFromDb; else { // 加鎖失敗,重試 // 休眠100ms重試 // 自旋 return getCatalogJsonFromDbithRedislock() }
階段四
已經(jīng)拿到了 lockvalue ,有了 UUID,但是過期了現(xiàn)在!其他人拿到所鎖設(shè)置了新值,于是 if 后將別人的鎖刪了??!也就是刪除鎖不是原子操作。
Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); String lockValue = redisTemplate.opsForValue().get("lock"); if(uuid.equals(lockValue)) { // 刪除我自己的鎖 redisTemplate.delete("lock"); }
問題場景
如果正好判斷是當前值,正要刪除鎖時,鎖已過期,別人已設(shè)置成功新值。那刪除的就是別人的鎖.
解決方案
刪除鎖必須保證原子性。使用redis+Lua腳本。
階段五
確保加鎖/解鎖都是原子操作
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; 關(guān)注公眾號:麒麟改bug,可獲取Redis實戰(zhàn)學(xué)習筆記一份。
保證加鎖【占位+過期時間】和刪除鎖【判斷+刪除】的原子性。 更難的事情,鎖的自動續(xù)期。
到此,關(guān)于“怎么用Redis鎖”的學(xué)習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習,快去試試吧!若想繼續(xù)學(xué)習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。