Spring?Boot?3.0x的Redis?分布式鎖的概念和原理
Spring Boot 中的 Redis 分布式鎖
在分布式系統(tǒng)中,多個(gè)進(jìn)程同時(shí)訪問共享資源時(shí),很容易出現(xiàn)并發(fā)問題。為了避免這些問題,我們可以使用分布式鎖來保證共享資源的獨(dú)占性。Redis 是一款非常流行的分布式緩存,它也提供了分布式鎖的功能。在 Spring Boot 中,我們可以很容易地使用 Redis 分布式鎖來管理并發(fā)訪問。
本文將介紹 Redis 分布式鎖的概念和原理,并說明如何在 Spring Boot 中使用它們。
Redis 分布式鎖的概念和原理
Redis 分布式鎖是一種基于 Redis 的分布式鎖解決方案。它的原理是利用 Redis 的原子性操作實(shí)現(xiàn)鎖的獲取和釋放,從而保證共享資源的獨(dú)占性。

spring boot 項(xiàng)目引入
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
<version>2.2.7</version>
</dependency>在需要加分布式鎖的方法上,添加注解@Lock4j
1.@Lock4j 注解的功能
獲取鎖超時(shí)(acquireTimeout):指定在獲取鎖時(shí)的等待時(shí)間,默認(rèn)情況下是 3 秒。如果在這段時(shí)間內(nèi)無法獲取到鎖,可能會(huì)拋出異?;蜻M(jìn)行相應(yīng)的處理。
鎖過期時(shí)間(expire):指定鎖的過期時(shí)間,默認(rèn)是 30 秒。如果在這段時(shí)間內(nèi)鎖沒有被手動(dòng)釋放,它會(huì)自動(dòng)失效。這個(gè)機(jī)制通常用于防止死鎖。
SpEL 表達(dá)式支持:@Lock4j 支持使用 SpEL 表達(dá)式來動(dòng)態(tài)生成鎖的鍵(key),例如通過方法參數(shù)生成唯一的鎖標(biāo)識(shí)。
@Service
public class DemoServiceImpl {
/**
默認(rèn)獲取鎖超時(shí)3秒,30秒鎖過期
這個(gè)方法使用了 @Lock4j 注解,并且沒有顯式地配置任何參數(shù)。
默認(rèn)行為:獲取鎖時(shí)的超時(shí)時(shí)間為 3 秒,鎖的過期時(shí)間為 30 秒。
適用場景:在簡單的場景下,simple() 方法會(huì)被鎖住,直到鎖被釋放或超時(shí)。在鎖的持有期間,其他線程無法進(jìn)入該方法。
**/
@Lock4j
public void simple() {
//需要執(zhí)行的方法
}
/**
完全配置,支持spel,這個(gè)方法使用了 @Lock4j 注解,并且自定義了多個(gè)參數(shù)。
配置詳解:
keys = {"#user.id", "#user.name"}:使用 SpEL 表達(dá)式動(dòng)態(tài)生成鎖的鍵。這里鎖的鍵由 user 對(duì)象的 id 和 name 屬性組成,確保了鎖的唯一性。
expire = 60000:指定鎖的過期時(shí)間為 60 秒(即1分鐘)。
acquireTimeout = 1000:指定獲取鎖的超時(shí)時(shí)間為 1 秒。
適用場景:當(dāng)方法涉及到特定用戶操作時(shí),使用 customMethod() 來確保同一用戶(根據(jù) id 和 name 唯一確定)不會(huì)被多個(gè)線程同時(shí)操作。只有在獲取到鎖的情況下,才會(huì)執(zhí)行方法邏輯,鎖在1秒內(nèi)未獲取到,則會(huì)拋出異?;驁?zhí)行相應(yīng)處理。
**/
@Lock4j(keys = {"#user.id", "#user.name"}, expire = 60000, acquireTimeout = 1000)
public User customMethod(User user) {
return user;
}
}設(shè)置配置文件的
lock4j: acquire-timeout: 3000 # 默認(rèn)獲取鎖超時(shí)時(shí)間為3秒 expire: 30000 # 默認(rèn)鎖的過期時(shí)間為30秒 primary-executor: com.baomidou.lock.executor.RedisTemplateLockExecutor # 使用RedisTemplate作為默認(rèn)的鎖執(zhí)行器 lock-key-prefix: lock4j # 鎖key的前綴,默認(rèn)為lock4j
配置項(xiàng)詳解
acquire-timeout: 3000
含義:指定全局默認(rèn)的獲取鎖的超時(shí)時(shí)間,單位為毫秒。默認(rèn)設(shè)置為3秒(3000毫秒)。如果在這個(gè)時(shí)間內(nèi)未能獲取到鎖,將觸發(fā)相應(yīng)的處理邏輯(比如拋出異常)。
使用場景:適用于全局大多數(shù)鎖的場景,可以減少在每個(gè)注解中重復(fù)配置的需要。
expire: 30000
含義:指定全局默認(rèn)的鎖過期時(shí)間,單位為毫秒。默認(rèn)設(shè)置為30秒(30000毫秒)。在這個(gè)時(shí)間內(nèi),如果鎖沒有被釋放,它將自動(dòng)失效。
使用場景:適用于防止死鎖的全局場景,確保鎖在一定時(shí)間內(nèi)自動(dòng)釋放,避免持有鎖的線程因故障而導(dǎo)致鎖無法釋放。
primary-executor: com.baomidou.lock.executor.RedisTemplateLockExecutor
含義:指定默認(rèn)使用的分布式鎖執(zhí)行器。這個(gè)配置定義了使用哪種方式來實(shí)現(xiàn)鎖的邏輯,常見的選項(xiàng)包括 Redisson, RedisTemplate, 和 Zookeeper。
使用場景:這里指定使用 RedisTemplateLockExecutor 來實(shí)現(xiàn)分布式鎖邏輯,適用于大多數(shù)基于Redis的分布式系統(tǒng)。
lock-key-prefix: lock4j
含義:為鎖的鍵(key)指定一個(gè)全局前綴。這個(gè)前綴會(huì)被添加到所有的鎖鍵之前,以確保鎖鍵的唯一性。
使用場景:適用于多個(gè)應(yīng)用共享一個(gè)Redis實(shí)例時(shí),通過設(shè)置前綴來防止不同應(yīng)用之間的鎖鍵沖突。
用法
@Lock4j(executor = RedissonLockExecutor.class)
public Boolean test() {
return "true";
}自定義鎖key生成器,默認(rèn)的鎖key生成器為 com.baomidou.lock.DefaultLockKeyBuilder
@Component
public class DynamicLockKeyBuilder extends DefaultLockKeyBuilder {
@Override
public String buildKey(MethodInvocation invocation, String[] definitionKeys) {
String key = super.buildKey(invocation, definitionKeys);
//需要執(zhí)行的方法
return key;
}
}自定義鎖獲取失敗策略,默認(rèn)的鎖獲取失敗策略為 com.baomidou.lock.DefaultLockFailureStrategy
@Component
public class MyLockFailureStrategy implements LockFailureStrategy {
@Override
public void onLockFailure(String key, long acquireTimeout, int acquireCount) {
//需要執(zhí)行的方法或者業(yè)務(wù)代碼
}
}手動(dòng)上鎖或手動(dòng)解鎖
@Service
@AllArgsConstructor
public class SysPaymentInfoServiceImpl extends ServiceImpl<SysPaymentInfoMapper, SysPaymentInfo> implements SysPaymentInfoService {
private final LockTemplate lockTemplate;
public void programmaticLock(String userId) {
// 執(zhí)行查詢業(yè)務(wù)操作 不上鎖
// 業(yè)務(wù)區(qū)域
// 獲取鎖
final LockInfo lockInfo = lockTemplate.lock(userId, 30000L, 5000L, RedissonLockExecutor.class);
if (null == lockInfo) {
throw new RuntimeException("業(yè)務(wù)處理中,請(qǐng)稍后再試!");
}
// 獲取鎖成功,處理相關(guān)業(yè)務(wù)
try {
Console.log("執(zhí)行簡單方法 , 當(dāng)前線程:" + Thread.currentThread().getName() + " , counter:" + (counter++));
} finally {
//釋放鎖
lockTemplate.releaseLock(lockInfo);
}
//結(jié)束
}指定時(shí)間內(nèi)不釋放鎖(限流)
// 用戶在5秒內(nèi)只能訪問1次
@Lock4j(keys = {"#user.id"}, acquireTimeout = 0, expire = 5000, autoRelease = false)
public Boolean test(User user) {
return "true";
}1.@Lock4j(keys = {“#user.id”})
含義:使用 SpEL 表達(dá)式 #user.id 生成鎖的鍵。鎖的鍵與傳入的 user.id 關(guān)聯(lián),確保鎖的唯一性。這樣可以保證每個(gè)用戶(根據(jù)其 id)都會(huì)有一個(gè)唯一的鎖。
2.acquireTimeout = 0
含義:獲取鎖的超時(shí)時(shí)間設(shè)置為 0,表示立即嘗試獲取鎖,不等待。如果無法獲取鎖,則直接放棄操作。
使用場景:當(dāng)你希望方法調(diào)用立即失敗而不等待時(shí),這個(gè)配置很有用。適用于需要快速響應(yīng)的場景。
3.expire = 5000
含義:鎖的過期時(shí)間設(shè)置為 5000 毫秒(5 秒)。鎖在 5 秒后自動(dòng)失效,釋放鎖資源。
使用場景:這個(gè)配置用于控制用戶只能在 5 秒內(nèi)訪問一次該方法,5 秒后鎖自動(dòng)失效,用戶可以再次訪問。
4.autoRelease = false
含義:設(shè)置 autoRelease = false 表示鎖不會(huì)在方法執(zhí)行完畢后自動(dòng)釋放。通常,默認(rèn)情況下,鎖在方法執(zhí)行完畢后會(huì)自動(dòng)釋放,但在這里顯式關(guān)閉了這個(gè)功能。
使用場景:這種配置可能用于場景中需要手動(dòng)控制鎖的釋放,而不是依賴方法執(zhí)行結(jié)束后自動(dòng)釋放的情況。例如,你可能希望鎖在一定時(shí)間后自然過期,而不是方法執(zhí)行完畢就立即釋放。
到此這篇關(guān)于適合 Spring Boot 3.0x的Redis 分布式鎖的文章就介紹到這了,更多相關(guān)Spring Boot Redis 分布式鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis實(shí)現(xiàn)限流器的三種方法(小結(jié))
本文主要介紹了Redis實(shí)現(xiàn)限流器的三種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
redis列表類型_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了redis列表類型的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
基于session?Redis實(shí)現(xiàn)登錄
這篇文章主要介紹了基于session?Redis實(shí)現(xiàn)登錄的相關(guān)資料,需要的朋友可以參考下2023-10-10
詳解Redis SCAN命令實(shí)現(xiàn)有限保證的原理
這篇文章主要介紹了Redis SCAN命令實(shí)現(xiàn)有限保證的原理,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-07-07
Redis集群水平擴(kuò)展、集群中添加以及刪除節(jié)點(diǎn)的操作
這篇文章主要介紹了Redis集群水平擴(kuò)展、集群中添加以及刪除節(jié)點(diǎn)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03
Redis安裝啟動(dòng)及常見數(shù)據(jù)類型
這篇文章主要介紹了Redis安裝啟動(dòng)及常見數(shù)據(jù)類型,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04

