成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

SpringBoot使用Redis實現分布式鎖

瀏覽:2日期:2023-05-17 11:00:28

前言

在單機應用時代,我們對一個共享的對象進行多線程訪問的時候,使用java的synchronized關鍵字或者ReentrantLock類對操作的對象加鎖就可以解決對象的線程安全問題。

分布式應用時代這個方法卻行不通了,我們的應用可能被部署到多臺機器上,運行在不同的JVM里,一個對象可能同時存在多臺機器的內存中,怎樣使共享對象同時只被一個線程處理就成了一個問題。

在分布式系統中為了保證一個對象在高并發的情況下只能被一個線程使用,我們需要一種跨JVM的互斥機制來控制共享資源的訪問,此時就需要用到我們的分布式鎖了。

分布式鎖一般有三種實現方式:1.通過數據庫實現分布式鎖;2.通過緩存(Redis等)實現分布式鎖;3.通過Zookeeper實現分布式鎖。本篇文章主要介紹第二種通過Redis實現分布式鎖的方式。

分布式鎖的需要具備的條件

為了保證分布式鎖的可用性,需要具備一下五點條件:

1、在同一時間保證只有一臺機器的一個線程可以持有鎖。2、不能發生死鎖,無論何時持有鎖的機器崩潰掛掉了都要能自動釋放鎖。3、高效的獲取和釋放鎖。4、具備非阻塞性,一旦獲取不到鎖就立刻返回加鎖失敗。5、獨占性,即自己加的鎖只有自己才能釋放。

代碼實現

組件依賴

首先在pom.xml文件中添加依賴:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency>

加鎖代碼

代碼如下:

/** * 獲取鎖 * @param lockKey 鎖 * @param identity 身份標識(保證鎖不會被其他人釋放) * @param expireTime 鎖的過期時間(單位:秒) * @return */public boolean lock(String lockKey, String identity, long expireTime){ boolean lockResult = redisTemplate.opsForValue().setIfAbsent(lockKey, identity, expireTime, TimeUnit.SECONDS); return opsForValue;}

加鎖的方法只需要三個參數:lockKey、identity、expireTime。

第一個參數lockKey為key,一個資源對應一個唯一的key。 第二個參數identity為身份標識,作為此key對應的value存儲,為了判斷在釋放鎖時是不是和加鎖的身份相同,防止別人釋放鎖。 第三個參數expireTime為過期時間,此參數保證程序加鎖后崩潰導致不能主動釋放鎖的時候自動釋放鎖,防止出現死鎖。

為什么使用setIfAbsent方法呢?這個方法的好處就是,如果redis中已經存在這個key了,就會返回失敗,并且不改變redis中的數據,這樣就不會把別的線程的加的鎖給覆蓋掉。

解鎖代碼

代碼如下:

/** * 釋放鎖 * @param lockKey 鎖 * @param identity 身份標識(保證鎖不會被其他人釋放) * @return */public boolean releaseLock(String lockKey, String identity){ String luaScript = 'if ' + ' redis.call(’get’, KEYS[1]) == ARGV[1] ' + 'then ' + ' return redis.call(’del’, KEYS[1]) ' + 'else ' + ' return 0 ' + 'end'; DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(); redisScript.setResultType(Boolean.class); redisScript.setScriptText(luaScript); List<String> keys = new ArrayList<>(); keys.add(lockKey); boolean result = redisTemplate.execute(redisScript, keys, identity); return result;}

解鎖的方法只需兩個參數:lockKey、identity。

第一個參數lockKey為key,一個資源對應一個唯一的key。 第二個參數identity為身份標識,作為此key對應的value存儲,為了判斷在釋放鎖時是不是和加鎖的身份相同,防止別人釋放鎖。

此處使用Lua腳本來判斷身份,身份相同就刪除,身份不同就不對數據做操作并返回失敗。為什么要使用Lua腳本呢?這是為了要保證操作的原子性,redis在執行Lua腳本的時候是把腳本當作一個命令來執行的,我們都知道redis的命令是都是原子操作,這樣就保證了操作的原子性。

測試代碼

package com.qixi.lock.demo.lockdemo.controller;import com.qixi.lock.demo.lockdemo.util.RedisLock;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;/** * 測試分布式鎖 * @author ZhengNC * @date 2020/5/13 17:27 */@RestController@RequestMapping('test')public class TestRedisLockController { private final String lockKeyName = 'testKey'; @Autowired private RedisLock redisLock; /** * 測試加鎖 * @param id 加鎖的資源id * @param identity 身份標識 * @return */ @GetMapping('lock') public String lock(@RequestParam('id') String id, @RequestParam('identity') String identity){ String lockKey = lockKeyName+':'+id; boolean lockSuccess = redisLock.lock(lockKey, identity, 60); String result = 'lock failed'; if (lockSuccess){ result = 'lock success'; } return result; } /** * 測試釋放鎖 * @param id 釋放鎖的資源id * @param identity 身份標識 * @return */ @GetMapping('release') public String release(@RequestParam('id') String id, @RequestParam('identity') String identity){ String lockKey = lockKeyName+':'+id; boolean releaseSuccess = redisLock.releaseLock(lockKey, identity); String result = 'release failed'; if (releaseSuccess){ result = 'release success'; } return result; }}

package com.qixi.lock.demo.lockdemo.util;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.script.DefaultRedisScript;import org.springframework.stereotype.Component;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;/** * 分布式鎖Redis工具類 * @author ZhengNC * @date 2020/5/13 17:27 */@Componentpublic class RedisLock { @Autowired private RedisTemplate<String, String> redisTemplate; /** * 獲取鎖 * @param lockKey 鎖 * @param identity 身份標識(保證鎖不會被其他人釋放) * @param expireTime 鎖的過期時間(單位:秒) * @return */ public boolean lock(String lockKey, String identity, long expireTime){ boolean lockResult = redisTemplate.opsForValue().setIfAbsent(lockKey, identity, expireTime, TimeUnit.SECONDS); return lockResult; } /** * 釋放鎖 * @param lockKey 鎖 * @param identity 身份標識(保證鎖不會被其他人釋放) * @return */ public boolean releaseLock(String lockKey, String identity){ String luaScript ='if ' +' redis.call(’get’, KEYS[1]) == ARGV[1] ' +'then ' +' return redis.call(’del’, KEYS[1]) ' +'else ' +' return 0 ' +'end'; DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(); redisScript.setResultType(Boolean.class); redisScript.setScriptText(luaScript); List<String> keys = new ArrayList<>(); keys.add(lockKey); boolean result = redisTemplate.execute(redisScript, keys, identity); return result; }}

結語

感謝大家閱讀我的文章,更歡迎大家指出我的問題,希望能在這里通過討論取得共同的進步。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Spring
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
日韩亚洲电影在线| 国内精品在线播放| 久久99国产精品尤物| 亚洲精选久久| 91电影在线观看| 亚洲天堂av老司机| 欧美福利精品| 久久久精品国产99久久精品芒果| 蜜桃91丨九色丨蝌蚪91桃色| 亚洲精品麻豆| 亚洲欧美另类图片小说| 色综合天天性综合| 久久精品欧美日韩| 99久久久免费精品国产一区二区| 欧美高清激情brazzers| 久久国产成人午夜av影院| 麻豆成人av| 亚洲电影激情视频网站| 免费在线日韩av| 亚洲亚洲人成综合网络| 亚洲一区二区动漫| 亚洲国产欧美日韩另类综合| 国产女主播一区二区三区| 亚洲一区二区三区四区五区黄| 91久久国产综合久久蜜月精品| 国产精品国产三级国产三级人妇| 午夜精品短视频| 国产精品久久久久婷婷二区次| 午夜久久福利| 国产精品传媒在线| 影音先锋中文字幕一区二区| 亚洲欧美自拍偷拍色图| 一区视频在线| 亚洲精品高清视频在线观看| 成人丝袜18视频在线观看| 欧美一区二区视频在线观看2020 | 国产日产欧美精品一区二区三区| 91小视频在线| 国产精品视频第一区| 亚洲国产精品www| 亚洲激情一二三区| 久久久久久婷| 久久99国产精品麻豆| 欧美一区二区在线免费观看| 成人午夜短视频| 久久久久久日产精品| 欧美日韩视频一区二区三区| 亚洲人成网站在线| 午夜在线精品| 免费成人在线观看| 666欧美在线视频| 成人午夜短视频| 日韩亚洲欧美一区二区三区| av电影在线观看一区| 国产精品视频线看| 久久国产成人| 国产精品一区专区| 欧美国产97人人爽人人喊| 亚洲激情国产| 日本欧洲一区二区| 欧美一区二区私人影院日本| 91视频你懂的| 亚洲在线观看免费视频| 色av成人天堂桃色av| 久久99九九99精品| 精品国产乱码久久久久久图片 | 欧美午夜免费| 性欧美疯狂xxxxbbbb| 亚洲欧洲精品一区| 日韩精品一级中文字幕精品视频免费观看| 欧美色综合天天久久综合精品| 高清国产午夜精品久久久久久| 亚洲国产精品99久久久久久久久| 一区二区三区四区五区在线| 美女任你摸久久| 337p粉嫩大胆色噜噜噜噜亚洲| 一区在线电影| 久久99这里只有精品| 精品国产伦理网| 国产日韩欧美三区| 国产精品69毛片高清亚洲| 国产欧美日韩一区二区三区在线观看| 亚洲欧美电影在线观看| 国产麻豆精品在线| 国产精品久久久久久久第一福利| 久久美女性网| 波多野结衣中文字幕一区二区三区 | 国产精品红桃| 三级久久三级久久| 日韩视频在线永久播放| 伊人久久综合| 精品一区二区三区在线视频| 国产欧美一区二区精品秋霞影院| 亚洲性人人天天夜夜摸| 久久精品国产免费| 欧美激情中文字幕| 色婷婷av一区二区三区大白胸| 成人少妇影院yyyy| 亚洲欧美电影院| 正在播放一区二区| 尤物精品在线| 黑人精品欧美一区二区蜜桃 | 不卡一卡二卡三乱码免费网站| 亚洲色图色小说| 欧美色精品在线视频| 欧美高清一区二区| 蜜臀av一区二区在线观看| 国产精品系列在线| 久久av二区| 成人午夜激情片| 亚洲午夜久久久久久久久久久 | 亚洲高清不卡在线观看| 日韩欧美一级二级三级久久久| 在线精品观看| 国产一区二区毛片| 亚洲欧美一区二区不卡| 尤物精品在线| 国产精品 欧美精品| 亚洲综合色婷婷| 精品国产一二三区| 91久久精品一区二区二区| 91麻豆文化传媒在线观看| 蜜臀av性久久久久蜜臀av麻豆| 国产精品久久久一区麻豆最新章节| 欧美日韩在线三区| 国产情侣一区| 91视视频在线观看入口直接观看www | 日本道在线观看一区二区| 欧美福利专区| 国产在线精品视频| 亚洲chinese男男1069| 欧美国产禁国产网站cc| 欧美丰满美乳xxx高潮www| 亚洲一区尤物| 国产精品豆花视频| 成人毛片在线观看| 裸体一区二区三区| 亚洲另类色综合网站| 久久久久久亚洲综合影院红桃| 欧美影院午夜播放| 在线一区视频| 欧美日韩国产三区| 久久精品72免费观看| 亚洲国产欧美日韩另类综合| 国产日韩欧美一区二区三区乱码| 欧美日韩午夜在线| 久久亚洲图片| 国产精品日本| 欧美区一区二| 成人激情图片网| 韩国毛片一区二区三区| 五月婷婷色综合| 国产精品久久久久永久免费观看| 欧美大白屁股肥臀xxxxxx| 欧美怡红院视频| 免费亚洲婷婷| 一区二区亚洲| 欧美日本精品| 91在线无精精品入口| 国内精品久久久久影院一蜜桃| 日日欢夜夜爽一区| 亚洲国产一区二区在线播放| 亚洲欧洲av在线| 国产精品欧美精品| 久久久精品tv| 欧美不卡在线视频| 91精品国产色综合久久ai换脸| 欧洲精品中文字幕| 91久久香蕉国产日韩欧美9色| 免费亚洲一区二区| 小嫩嫩精品导航| 国产亚洲在线观看| 亚洲激情一区二区三区| 亚洲高清在线播放| 午夜精品久久99蜜桃的功能介绍| 91免费在线视频观看| 欧美一区精品| 91片黄在线观看| 91亚洲大成网污www| 91麻豆精品在线观看| 成人精品一区二区三区四区 | 5858s免费视频成人| 精品视频一区二区不卡| 91久久精品一区二区三| 色婷婷亚洲婷婷| 色94色欧美sute亚洲线路二| 亚洲综合精品四区| 亚洲制服av| 国语精品中文字幕| 在线免费观看欧美| 国产精品国产亚洲精品看不卡15| 欧美精品一区二区视频| 欧美黄在线观看| 欧美网站在线| 五月天激情综合网| 视频在线在亚洲| 免费成人在线网站| 免费看欧美美女黄的网站| 丝袜美腿亚洲一区| 男人的j进女人的j一区|