基於Redisson框架實現redis分散式鎖
阿新 • • 發佈:2022-03-23
1、起初
引入依賴
1 2 3 4 5 |
<!-- spring boot redis快取引入 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
|
controller層
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/**
* @author lj on 2021/2/28.
* @version 1.0
*/
public class IndexController {
@Autowired
private StringRedisTemplate redisTemplate;
@RequestMapping ( "/test" )
public String testRedisDis(){
final Boolean res = redisTemplate.opsForValue().setIfAbsent( "lock_key" , "liujun" );
if (!res){
return "error" ;
}
/**
* 執行程式碼業務
*/
return "end" ;
}
}
|
思考?帶來一系列的問題:
1、系統宕機,未釋放鎖即死鎖(redis設定過期時間,增加try...finally...程式碼段)
2、業務時間太長,釋放別人的鎖(設定redis值為唯一uuid;在釋放鎖時(redisTemplate.delete("key"),增加邏輯判斷只能釋放自己的鎖);增加看門狗來續時)
3、保證redis操作的原子性(redis設定值和設定過期時間必須同步)
2、進一步優化:
controller層
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/**
* @author lj on 2021/2/28.
* @version 1.0
*/
public class IndexController {
@Autowired
private StringRedisTemplate redisTemplate;
@RequestMapping ( "/test" )
public String testRedisDis(){
String lock_key = "prodect_001" ;
final String vaule = UUID.randomUUID().toString();
try {
final Boolean res = redisTemplate.opsForValue().setIfAbsent(lock_key, vaule, 30 , TimeUnit.SECONDS); //保證redis的原子性,設定時長防止redis死鎖
if (!res){
return "error" ;
}
//TODO 開闢一個分執行緒使用定時器進行redis續時
/**
* 執行程式碼業務
*/
} finally {
//釋放鎖
if (vaule.equals(redisTemplate.opsForValue().get(lock_key))){ //防止釋放別人的鎖
redisTemplate.delete( "lock_key" );
}
return "end" ;
}
}
}
|
3、使用Redisson框架
1、引入Redisson的依賴
1 2 3 4 5 |
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version> 3.6 . 5 </version>
</dependency>
|
2、配置為單機模式
1 2 3 4 5 6 7 |
@Bean
public Redisson redisson(){
//此為單機模式
final Config config = new Config();
config.useSingleServer().setAddress( "127.0.0.1:6379" ).setDatabase( 0 );
return (Redisson) Redisson.create(config);
}
|
3、簡單的使用程式碼片段
整個流程:
watch dog自動延期機制
客戶端1加鎖的鎖key預設生存時間才30秒,如果超過了30秒,客戶端1還想一直持有這把鎖,怎麼辦呢?
簡單!只要客戶端1一旦加鎖成功,就會啟動一個watch dog看門狗,他是一個後臺執行緒,會每隔10秒檢查一下,如果客戶端1還持有鎖key,那麼就會不斷的延長鎖key的生存時間。
如果時叢集的話還有一個問題:就是redis的master節點宕機了,而鎖沒來得及複製到slave節點(待處理。。。)
總結:redisson框架其實就是上面redis過程的優化;
先拿setnx來爭搶鎖,搶到之後,再用expire給鎖加一個過期時間防止鎖忘記了釋放;搶到鎖後會開闢一個分執行緒看門狗去續時,最後在finally程式碼快中刪除鎖。