1. 程式人生 > 其它 >基於Redisson框架實現redis分散式鎖

基於Redisson框架實現redis分散式鎖

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程式碼快中刪除鎖。