簡潔實(shí)用的Redis分布式鎖用法

Redis分布式鎖原理概述


首先Redis客戶端獲取當(dāng)前系統(tǒng)時(shí)間,以毫秒為單位; 然后客戶端會(huì)順序地嘗試向Redis集群中的每個(gè)節(jié)點(diǎn)獲取鎖,其具體步驟是使用相同的鍵Key名和隨機(jī)值;在向每個(gè)Redis節(jié)點(diǎn)獲取鎖的過程中,客戶端會(huì)以比鎖過期時(shí)間小得多的時(shí)間來設(shè)定超時(shí)機(jī)制,例如鎖的整個(gè)超時(shí)時(shí)間為10秒,集群有5個(gè)節(jié)點(diǎn),那么每個(gè)節(jié)點(diǎn)獲取鎖的超時(shí)時(shí)間可能會(huì)被限制在5~50毫秒之間,這是為了防止在某個(gè)節(jié)點(diǎn)不可用的情況下,客戶端等待時(shí)間過長,造成性能阻塞; 之后隨著各節(jié)點(diǎn)獲取鎖結(jié)果的反饋,Redis客戶端會(huì)對(duì)獲取情況進(jìn)行判斷,如果獲取各節(jié)點(diǎn)鎖的總時(shí)間小于鎖的超時(shí)時(shí)間設(shè)置,并且成功獲取鎖的節(jié)點(diǎn)數(shù)目大于N/2+1個(gè)(例如5個(gè)節(jié)點(diǎn)至少要有3個(gè)節(jié)點(diǎn)成功獲取鎖),滿足上述條件的情況下,Redis客戶端才會(huì)認(rèn)為獲取鎖成功,否則就會(huì)認(rèn)為鎖獲取失敗,并依次釋放掉各個(gè)節(jié)點(diǎn)的鎖信息; 獲取鎖成功后即可以安全地執(zhí)行操作,完成后再依次釋放各節(jié)點(diǎn)鎖持有的鎖信息;
互斥:任何時(shí)刻只能有一個(gè)Redis客戶端獲取鎖; 無死鎖:即使鎖定資源的服務(wù)崩潰或者分區(qū),仍然能釋放鎖); 容錯(cuò)性:只要多數(shù)redis節(jié)點(diǎn)(一半以上)在使用,Redis客戶端就可以獲取和釋放鎖;
Spring Boot集成使用方式

1)在工程pom.xml文件中引入Spring Integration依賴,代碼如下:
<dependency>
????<groupId>org.springframework.bootgroupId>
????<artifactId>spring-boot-starter-integrationartifactId>
dependency>
<dependency>
????<groupId>org.springframework.integrationgroupId>
????<artifactId>spring-integration-redisartifactId>
dependency>
目前Spring所提供的分布式鎖相關(guān)的代碼被遷移在Spring Integration子項(xiàng)目中,所以這里引入其相關(guān)依賴。
2)編寫RedisLock的配置類,代碼如下:
@Configuration
public?class?RedisLockConfiguration?{
????@Bean
????public?RedisLockRegistry?redisLockRegistry(RedisConnectionFactory?redisConnectionFactory)?{
????????return?new?RedisLockRegistry(redisConnectionFactory,?"payment");
????}
}以上配置代碼加載的前提在于應(yīng)用已經(jīng)集成了Redis服務(wù)訪問鏈接信息,具體Spring Boot項(xiàng)目集成Redis訪問的方式比較簡單可以參考其他資料。
3)分布式鎖的具體使用方式,代碼片段如下:
/**
?*?引入Redis分布式鎖依賴組件
?*/
@Autowired
private?RedisLockRegistry?redisLockRegistry;
@Override
public?UnifiedPayBO?unifiedPay(UnifiedPayDTO?unifiedPayDTO)?{
????...
????//創(chuàng)建Redis分布式鎖
????Lock?lock?=?redisLockRegistry.obtain(redisLockPrefix?+?unifiedPayDTO.getOrderId());
????try?{??????
????????//嘗試獲取鎖
????????boolean?isLock?=?lock.tryLock(1,?TimeUnit.SECONDS);
????????if?(isLock)?{
????????????//執(zhí)行業(yè)務(wù)邏輯
????????????...
????????}
????}?catch?(InterruptedException?e)?{
????????e.printStackTrace();
????}?finally?{
????????//釋放分布式鎖
????????lock.unlock();
????}
????...
}
上述代碼為訂單防重時(shí)使用Redis分布鎖的示例代碼,通過依賴注入RedisLockRegistry實(shí)例來實(shí)現(xiàn)分布式鎖的相關(guān)操作,例如obtain()方法創(chuàng)建鎖、tryLock()持有鎖及unlock()釋放鎖等。
—————END—————
推薦閱讀:
實(shí)戰(zhàn):一鍵生成前后端代碼,Mybatis-Plus代碼生成器讓我舒服了
為什么要重寫 hashcode 和 equals 方法?
SpringBoot @Value 解析集合配置
推薦閱讀:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
評(píng)論
圖片
表情
