基于Redis分布式鎖Redisson及SpringBoot集成Redisson
- 分布式鎖需要具備的條件和剛需
- 獨占性:OnlyOne,任何時刻只能有且僅有一個線程持有
- 高可用:若redis集群環(huán)境下,不能因為某一個節(jié)點掛了而出現(xiàn)獲取鎖和釋放鎖失敗的情況
- 防死鎖:杜絕死鎖,必須有超時控制機制或者撤銷操作,有個兜底終止跳出方案
- 不亂搶:防止張冠李戴,不能私下unlock別人的鎖,只能自己加鎖自己釋放
- 重入性:同一個節(jié)點的同一個線程如果獲得鎖之后,它也可以再次獲取這個鎖
- Redisson使用
引入 redisson 依賴:
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.16.2</version> </dependency>
添加 redisson 配置:
import org.redisson.Redisson; import org.redisson.config.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.io.Serializable; @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); // 設(shè)置key序列號方式string redisTemplate.setKeySerializer(new StringRedisSerializer()); // 設(shè)置value的序列化方式j(luò)son redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean public Redisson redisson() { Config config = new Config(); config.useSingleServer().setAddress("redis://192.168.10.233:6379").setDatabase(0); return (Redisson) Redisson.create(config); } }
接口測試:
import org.redisson.Redisson; import org.redisson.api.RLock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private Redisson redisson; private static final String KEY = "spike"; @GetMapping("/buy") public String bugGood() { RLock redissonLock = redisson.getLock(KEY); redissonLock.lock(); try { String result = stringRedisTemplate.opsForValue().get("goods:001"); int goodNumber = result == null ? 0 : Integer.parseInt(result); if (goodNumber > 0) { int realNum = goodNumber - 1; stringRedisTemplate.opsForValue().set("goods:001", realNum + ""); return "秒殺成功,剩余庫存:" + realNum; } return "商品已售罄!"; } finally { redissonLock.unlock(); } } }
多節(jié)點的情況下,代碼相同,要保證 lock 的 key 一樣
- SpringBoot集成Redisson
引入 redis 和 redisson starter:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.redisson/redisson --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> </dependency>
redis 配置:
spring: redis: # 地址 host: 192.168.20.26 # 端口,默認為6379 port: 6379 password: 123456 # 連接超時時間 timeout: 30s database: 0 lettuce: pool: # 連接池中的最小空閑連接 min-idle: 0 # 連接池中的最大空閑連接 max-idle: 8 # 連接池的最大數(shù)據(jù)庫連接數(shù) max-active: 8 # #連接池最大阻塞等待時間(使用負值表示沒有限制) max-wait: -1ms
redisson配置:
import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.redisson.config.SingleServerConfig; import org.redisson.config.TransportMode; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * redisson配置 */ @Configuration public class RedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private String port; @Value("${spring.redis.password}") private String password; @Bean public RedissonClient redissonClient() { Config config = new Config(); config.setTransportMode(TransportMode.NIO); // 單體配置,如果是SSL連接,使用 rediss:// SingleServerConfig singleServerConfig = config.useSingleServer(); singleServerConfig.setAddress("redis://" + host + ":" + port); singleServerConfig.setPassword(password); return Redisson.create(config); } }
使用:
import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import javax.annotation.Resource; import java.util.concurrent.TimeUnit; public class TestController { @Resource private RedissonClient redissonClient; public void doAction1() { String lockKey = "lockKey"; RLock lock = redissonClient.getLock(lockKey); // 加鎖,無參數(shù) lock.lock(); // 鎖有效時間,時間單位 // lock.lock(5, TimeUnit.SECONDS); try { // do something } finally { // 解鎖 lock.unlock(); } } public void doAction2() throws InterruptedException { String lockKey = "lockKey"; RLock lock = redissonClient.getLock(lockKey); // 1. 無參數(shù),直接上鎖 // lock.tryLock(); // 2. 等待時間,時間單位 // lock.tryLock(3, TimeUnit.SECONDS); // 3. 等待時間,鎖有效時間,時間單位 // lock.tryLock(3, 5, TimeUnit.SECONDS); try { // 常規(guī)寫法 if (lock.tryLock(3, 5, TimeUnit.SECONDS)) { // do something } else { // 沒有獲取到鎖 } } finally { // 解鎖 lock.unlock(); } } }
到此這篇關(guān)于基于Redis分布式鎖Redisson及SpringBoot集成Redisson的文章就介紹到這了,更多相關(guān)Redis分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java操作minio刪除文件夾及其文件方法(MinIO基本使用)
MinIO是一個高性能、無限擴展的開源對象存儲服務(wù)器,它以對象的形式存儲數(shù)據(jù),并兼容Amazon S3接口,它適用于大規(guī)模數(shù)據(jù)存儲、大數(shù)據(jù)分析、文件共享和備份等應(yīng)用場景,這篇文章主要介紹了java操作minio刪除文件夾及其文件方法,需要的朋友可以參考下2024-02-02詳解Eclipse Validating緩慢的優(yōu)化
這篇文章主要介紹了詳解Eclipse Validating緩慢的優(yōu)化,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03SpringBoot項目中忽略某屬性返回數(shù)據(jù)給前端
在Spring Boot中,保護敏感信息和減少數(shù)據(jù)傳輸是很重要的,我們可以使用多種方法來忽略返回數(shù)據(jù)中的字段,無論是使用@JsonIgnore注解、Projection投影、@JsonIgnoreProperties注解還是自定義序列化器,都能達到我們的目的,在實際應(yīng)用中,根據(jù)具體場景和需求選擇合適的方法2024-05-05MyBatis在insert插入操作時返回主鍵ID的配置(推薦)
這篇文章主要介紹了MyBatis在insert插入操作時返回主鍵ID的配置的相關(guān)資料,需要的朋友可以參考下2017-10-10Spring Boot集成Quartz注入Spring管理的類的方法
本篇文章主要介紹了Spring Boot集成Quartz注入Spring管理的類的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04Java經(jīng)典算法匯總之選擇排序(SelectionSort)
選擇排序也是比較簡單的一種排序方法,原理也比較容易理解,選擇排序在每次遍歷過程中只記錄下來最小的一個元素的下標,待全部比較結(jié)束之后,將最小的元素與未排序的那部分序列的最前面一個元素交換,這樣就降低了交換的次數(shù),提高了排序效率。2016-04-04