redis分布式锁 在集群模式下如何实现_收藏慢慢看系列:简洁实用的Redis分布式锁用法...
在微服務中很多情況下需要使用到分布式鎖功能,而目前比較常見的方案是通過Redis來實現分布式鎖,網上關于分布式鎖的實現方式有很多,早期主要是基于Redisson等客戶端,但在Spring Boot2.x以上版本中使用Redis時,其客戶端庫已經默認使用lettuce。
所以本文將直接介紹在Spring Boot2.x以上項目中快速使用Redis分布式鎖的功能的方法,希望能夠更新你的知識庫!
Redis分布式鎖原理概述
實際上Redis服務本身并不提供分布式鎖這樣的機制,但是作為全局Key-Value存儲系統,客戶端可以利用Redis提供的基本功能并通過一定的算法設計來實現分布式鎖功能。目前已有不少博客文章及代碼庫描述了如何使用Redis來實現分布式鎖,但是許多實現相對比較簡單,安全性也比較低。在Redis的官方文檔中推薦了一種叫做RedLock的算法來實現基于Redis的分布式鎖功能,現階段已存在基于該算法的多種語言版本的Redis客戶端實現庫。其中Java領域最為知名的是Redisson庫。但由于Redisson不僅實現了分布式鎖功能,還額外實現了一套Redis分布式數據結構,因此會顯得比較重,加上最新的基于Spring Boot.2.x以上版本使用Redis時,其客戶端庫已經默認使用了lettuce(比Redisson、Jedis線程更安全、更輕量級的一種Java Redis客戶端庫)的封裝,所以為了更加符合微服務場景下的使用,在實踐中往往會選擇基于RedLock算法自行實現分布式鎖。
本案例也將演示如何RedLock算法來實現Redis分布式鎖功能,不過在此之前讓我們先來看看RedLock算法是如何運行的,示意圖如下:
以上就是實現Redis分布式鎖官方推薦的RedLock算法邏輯,它是一種多節點Redis的分布式鎖算法,可以有效防止單節點故障問題。其執行步驟說明如下:
- 首先Redis客戶端獲取當前系統時間,以毫秒為單位;
 - 然后客戶端會順序地嘗試向Redis集群中的每個節點獲取鎖,其具體步驟是使用相同的鍵Key名和隨機值;在向每個Redis節點獲取鎖的過程中,客戶端會以比鎖過期時間小得多的時間來設定超時機制,例如鎖的整個超時時間為10秒,集群有5個節點,那么每個節點獲取鎖的超時時間可能會被限制在5~50毫秒之間,這是為了防止在某個節點不可用的情況下,客戶端等待時間過長,造成性能阻塞;
 - 之后隨著各節點獲取鎖結果的反饋,Redis客戶端會對獲取情況進行判斷,如果獲取各節點鎖的總時間小于鎖的超時時間設置,并且成功獲取鎖的節點數目大于N/2+1個(例如5個節點至少要有3個節點成功獲取鎖),滿足上述條件的情況下,Redis客戶端才會認為獲取鎖成功,否則就會認為鎖獲取失敗,并依次釋放掉各個節點的鎖信息;
 - 獲取鎖成功后即可以安全地執行操作,完成后再依次釋放各節點鎖持有的鎖信息;
 
實現上述算法的Redis客戶端可以基本上保證分布式鎖的有效性及安全性的幾個基本特性要求:
- 互斥:任何時刻只能有一個Redis客戶端獲取鎖;
 - 無死鎖:即使鎖定資源的服務崩潰或者分區,仍然能釋放鎖);
 - 容錯性:只要多數redis節點(一半以上)在使用,Redis客戶端就可以獲取和釋放鎖;
 
Spring Boot集成使用方式
通過前面內容的描述,相信你對實現Redis分布式鎖的基本算法應該有了一定的認識和理解。而在實踐的過程中可以依據該算法自行定制實現,但實際上Spring早就提供了基于該算法的Redis的分布式鎖的實現。其具體使用步驟如下:
1)在工程pom.xml文件中引入Spring Integration依賴,代碼如下:
<!-- spring integration -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<!-- spring integration與redis結合,實現redis分布式鎖 -->
<dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-redis</artifactId>
</dependency>目前Spring所提供的分布式鎖相關的代碼被遷移在Spring Integration子項目中,所以這里引入其相關依賴。
2)編寫RedisLock的配置類,代碼如下:
@Configuration
public class RedisLockConfiguration {@Beanpublic RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {return new RedisLockRegistry(redisConnectionFactory, "payment");}
}以上配置代碼加載的前提在于應用已經集成了Redis服務訪問鏈接信息,具體Spring Boot項目集成Redis訪問的方式比較簡單可以參考其他資料。
3)分布式鎖的具體使用方式,代碼片段如下:
/*** 引入Redis分布式鎖依賴組件*/
@Autowired
private RedisLockRegistry redisLockRegistry;@Override
public UnifiedPayBO unifiedPay(UnifiedPayDTO unifiedPayDTO) {...//創建Redis分布式鎖Lock lock = redisLockRegistry.obtain(redisLockPrefix + unifiedPayDTO.getOrderId());try {      //嘗試獲取鎖boolean isLock = lock.tryLock(1, TimeUnit.SECONDS);if (isLock) {//執行業務邏輯...}} catch (InterruptedException e) {e.printStackTrace();} finally {//釋放分布式鎖lock.unlock();}...
}上述代碼為訂單防重時使用Redis分布鎖的示例代碼,通過依賴注入RedisLockRegistry實例來實現分布式鎖的相關操作,例如obtain()方法創建鎖、tryLock()持有鎖及unlock()釋放鎖等。
寫在最后:
歡迎大家關注我新開通的公眾號【風平浪靜如碼】,海量Java相關文章,學習資料都會在里面更新,整理的資料也會放在里面。
覺得寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!
總結
以上是生活随笔為你收集整理的redis分布式锁 在集群模式下如何实现_收藏慢慢看系列:简洁实用的Redis分布式锁用法...的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 昼锦堂画是谁画的啊?
 - 下一篇: 11月份去日本要带什么,11月去日本哪里