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

spring boot 項目引入
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
<version>2.2.7</version>
</dependency>在需要加分布式鎖的方法上,添加注解@Lock4j
1.@Lock4j 注解的功能
獲取鎖超時(acquireTimeout):指定在獲取鎖時的等待時間,默認(rèn)情況下是 3 秒。如果在這段時間內(nèi)無法獲取到鎖,可能會拋出異常或進行相應(yīng)的處理。
鎖過期時間(expire):指定鎖的過期時間,默認(rèn)是 30 秒。如果在這段時間內(nèi)鎖沒有被手動釋放,它會自動失效。這個機制通常用于防止死鎖。
SpEL 表達式支持:@Lock4j 支持使用 SpEL 表達式來動態(tài)生成鎖的鍵(key),例如通過方法參數(shù)生成唯一的鎖標(biāo)識。
@Service
public class DemoServiceImpl {
/**
默認(rèn)獲取鎖超時3秒,30秒鎖過期
這個方法使用了 @Lock4j 注解,并且沒有顯式地配置任何參數(shù)。
默認(rèn)行為:獲取鎖時的超時時間為 3 秒,鎖的過期時間為 30 秒。
適用場景:在簡單的場景下,simple() 方法會被鎖住,直到鎖被釋放或超時。在鎖的持有期間,其他線程無法進入該方法。
**/
@Lock4j
public void simple() {
//需要執(zhí)行的方法
}
/**
完全配置,支持spel,這個方法使用了 @Lock4j 注解,并且自定義了多個參數(shù)。
配置詳解:
keys = {"#user.id", "#user.name"}:使用 SpEL 表達式動態(tài)生成鎖的鍵。這里鎖的鍵由 user 對象的 id 和 name 屬性組成,確保了鎖的唯一性。
expire = 60000:指定鎖的過期時間為 60 秒(即1分鐘)。
acquireTimeout = 1000:指定獲取鎖的超時時間為 1 秒。
適用場景:當(dāng)方法涉及到特定用戶操作時,使用 customMethod() 來確保同一用戶(根據(jù) id 和 name 唯一確定)不會被多個線程同時操作。只有在獲取到鎖的情況下,才會執(zhí)行方法邏輯,鎖在1秒內(nèi)未獲取到,則會拋出異?;驁?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)獲取鎖超時時間為3秒 expire: 30000 # 默認(rèn)鎖的過期時間為30秒 primary-executor: com.baomidou.lock.executor.RedisTemplateLockExecutor # 使用RedisTemplate作為默認(rèn)的鎖執(zhí)行器 lock-key-prefix: lock4j # 鎖key的前綴,默認(rèn)為lock4j
配置項詳解
acquire-timeout: 3000
含義:指定全局默認(rèn)的獲取鎖的超時時間,單位為毫秒。默認(rèn)設(shè)置為3秒(3000毫秒)。如果在這個時間內(nèi)未能獲取到鎖,將觸發(fā)相應(yīng)的處理邏輯(比如拋出異常)。
使用場景:適用于全局大多數(shù)鎖的場景,可以減少在每個注解中重復(fù)配置的需要。
expire: 30000
含義:指定全局默認(rèn)的鎖過期時間,單位為毫秒。默認(rèn)設(shè)置為30秒(30000毫秒)。在這個時間內(nèi),如果鎖沒有被釋放,它將自動失效。
使用場景:適用于防止死鎖的全局場景,確保鎖在一定時間內(nèi)自動釋放,避免持有鎖的線程因故障而導(dǎo)致鎖無法釋放。
primary-executor: com.baomidou.lock.executor.RedisTemplateLockExecutor
含義:指定默認(rèn)使用的分布式鎖執(zhí)行器。這個配置定義了使用哪種方式來實現(xiàn)鎖的邏輯,常見的選項包括 Redisson, RedisTemplate, 和 Zookeeper。
使用場景:這里指定使用 RedisTemplateLockExecutor 來實現(xiàn)分布式鎖邏輯,適用于大多數(shù)基于Redis的分布式系統(tǒng)。
lock-key-prefix: lock4j
含義:為鎖的鍵(key)指定一個全局前綴。這個前綴會被添加到所有的鎖鍵之前,以確保鎖鍵的唯一性。
使用場景:適用于多個應(yīng)用共享一個Redis實例時,通過設(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ù)代碼
}
}手動上鎖或手動解鎖
@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ù)處理中,請稍后再試!");
}
// 獲取鎖成功,處理相關(guān)業(yè)務(wù)
try {
Console.log("執(zhí)行簡單方法 , 當(dāng)前線程:" + Thread.currentThread().getName() + " , counter:" + (counter++));
} finally {
//釋放鎖
lockTemplate.releaseLock(lockInfo);
}
//結(jié)束
}指定時間內(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 表達式 #user.id 生成鎖的鍵。鎖的鍵與傳入的 user.id 關(guān)聯(lián),確保鎖的唯一性。這樣可以保證每個用戶(根據(jù)其 id)都會有一個唯一的鎖。
2.acquireTimeout = 0
含義:獲取鎖的超時時間設(shè)置為 0,表示立即嘗試獲取鎖,不等待。如果無法獲取鎖,則直接放棄操作。
使用場景:當(dāng)你希望方法調(diào)用立即失敗而不等待時,這個配置很有用。適用于需要快速響應(yīng)的場景。
3.expire = 5000
含義:鎖的過期時間設(shè)置為 5000 毫秒(5 秒)。鎖在 5 秒后自動失效,釋放鎖資源。
使用場景:這個配置用于控制用戶只能在 5 秒內(nèi)訪問一次該方法,5 秒后鎖自動失效,用戶可以再次訪問。
4.autoRelease = false
含義:設(shè)置 autoRelease = false 表示鎖不會在方法執(zhí)行完畢后自動釋放。通常,默認(rèn)情況下,鎖在方法執(zhí)行完畢后會自動釋放,但在這里顯式關(guān)閉了這個功能。
使用場景:這種配置可能用于場景中需要手動控制鎖的釋放,而不是依賴方法執(zhí)行結(jié)束后自動釋放的情況。例如,你可能希望鎖在一定時間后自然過期,而不是方法執(zhí)行完畢就立即釋放。
到此這篇關(guān)于適合 Spring Boot 3.0x的Redis 分布式鎖的文章就介紹到這了,更多相關(guān)Spring Boot Redis 分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入理解redis_memcached失效原理(小結(jié))
這篇文章主要介紹了深入理解redis_memcached失效原理(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
Redis高效查詢大數(shù)據(jù)的實踐與優(yōu)化詳細指南
Redis 是一種高性能的鍵值存儲數(shù)據(jù)庫,廣泛應(yīng)用于緩存,排行榜,計數(shù)器等場景,本文將圍繞如何高效查詢Redis中滿足條件的數(shù)據(jù)展開討論,感興趣的小伙伴可以了解下2025-04-04
基于Redis實現(xiàn)登錄功能思路詳解(手機號+驗證碼)
本文介紹了使用手機號和驗證碼登錄的方式,驗證碼通過控制臺輸出,重點解釋了UserServiceImpl實現(xiàn)類的結(jié)構(gòu),包括sendCode、login和createUserWithPhone方法,還介紹了攔截器框架,包括preHandle和攔截器鏈的配置,感興趣的朋友跟隨小編一起看看吧2026-01-01

