PowerJob UseCacheLock工作流程源碼剖析
序
本文主要研究一下PowerJob的UseCacheLock
UseCacheLock
tech/powerjob/server/core/lock/UseCacheLock.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCacheLock {
String type();
String key();
int concurrencyLevel();
}UseCacheLock注解定義了type、key、concurrencyLevel屬性
UseCacheLockAspect
tech/powerjob/server/core/lock/UseCacheLockAspect.java
@Slf4j
@Aspect
@Component
@Order(1)
@RequiredArgsConstructor
public class UseCacheLockAspect {
private final MonitorService monitorService;
private final Map<String, Cache<String, ReentrantLock>> lockContainer = Maps.newConcurrentMap();
private static final long SLOW_THRESHOLD = 100;
@Around(value = "@annotation(useCacheLock))")
public Object execute(ProceedingJoinPoint point, UseCacheLock useCacheLock) throws Throwable {
Cache<String, ReentrantLock> lockCache = lockContainer.computeIfAbsent(useCacheLock.type(), ignore -> {
int concurrencyLevel = useCacheLock.concurrencyLevel();
log.info("[UseSegmentLockAspect] create Lock Cache for [{}] with concurrencyLevel: {}", useCacheLock.type(), concurrencyLevel);
return CacheBuilder.newBuilder()
.initialCapacity(300000)
.maximumSize(500000)
.concurrencyLevel(concurrencyLevel)
.expireAfterWrite(30, TimeUnit.MINUTES)
.build();
});
final Method method = AOPUtils.parseMethod(point);
Long key = AOPUtils.parseSpEl(method, point.getArgs(), useCacheLock.key(), Long.class, 1L);
final ReentrantLock reentrantLock = lockCache.get(String.valueOf(key), ReentrantLock::new);
long start = System.currentTimeMillis();
reentrantLock.lockInterruptibly();
try {
long timeCost = System.currentTimeMillis() - start;
if (timeCost > SLOW_THRESHOLD) {
final SlowLockEvent slowLockEvent = new SlowLockEvent()
.setType(SlowLockEvent.Type.LOCAL)
.setLockType(useCacheLock.type())
.setLockKey(String.valueOf(key))
.setCallerService(method.getDeclaringClass().getSimpleName())
.setCallerMethod(method.getName())
.setCost(timeCost);
monitorService.monitor(slowLockEvent);
log.warn("[UseSegmentLockAspect] wait lock for method({}#{}) cost {} ms! key = '{}', args = {}, ", method.getDeclaringClass().getSimpleName(), method.getName(), timeCost,
key,
JSON.toJSONString(point.getArgs()));
}
return point.proceed();
} finally {
reentrantLock.unlock();
}
}
}UseCacheLockAspect攔截@UseCacheLock注解,它定義了lockContainer維護(hù)了useCacheLock.type()與Cache的關(guān)系;Cache采用的guava的Cache,其initialCapacity為300000,maximumSize為500000,expireAfterWrite為30分鐘;Cache的key為lock key,value為ReentrantLock;其execute方法主要是先執(zhí)行reentrantLock.lockInterruptibly(),然后執(zhí)行point.proceed(),最后reentrantLock.unlock();執(zhí)行point.proceed()之前還判斷了一下加鎖耗時(shí),若超過SLOW_THRESHOLD(100ms)則通過monitorService.monitor上報(bào)SlowLockEvent
示例
@UseCacheLock(type = "processJobInstance", key = "#instanceId", concurrencyLevel = 1024)
public void redispatchAsync(Long instanceId, int originStatus) {
// 將狀態(tài)重置為等待派發(fā)
instanceInfoRepository.updateStatusAndGmtModifiedByInstanceIdAndOriginStatus(instanceId, originStatus, InstanceStatus.WAITING_DISPATCH.getV(), new Date());
}key支持SpEl
小結(jié)
PowerJob的UseCacheLock注解定義了type、key、concurrencyLevel屬性;UseCacheLockAspect攔截@UseCacheLock注解,它定義了lockContainer維護(hù)了useCacheLock.type()與Cache的關(guān)系;而Cache的key為lock key,value為ReentrantLock,最后是通過reentrantLock.lockInterruptibly()加鎖。
以上就是PowerJob UseCacheLock工作流程源碼剖析的詳細(xì)內(nèi)容,更多關(guān)于PowerJob UseCacheLock的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springcloud檢索中間件?ElasticSearch?分布式場(chǎng)景的使用
單機(jī)的elasticsearch做數(shù)據(jù)存儲(chǔ),必然面臨兩個(gè)問題:海量數(shù)據(jù)存儲(chǔ)問題、單點(diǎn)故障問題,本文重點(diǎn)給大家介紹springcloud檢索中間件?ElasticSearch?分布式場(chǎng)景的運(yùn)用,感興趣的朋友跟隨小編一起看看吧2023-10-10
Java定時(shí)器通信協(xié)議管理模塊Timer詳解
這篇文章主要介紹了Java定時(shí)器通信協(xié)議管理模塊Timer,?Timer一般指定時(shí)器(通信協(xié)議管理模塊)人類最早使用的定時(shí)工具是沙漏或水漏,但在鐘表誕生發(fā)展成熟之后,人們開始嘗試使用這種全新的計(jì)時(shí)工具來改進(jìn)定時(shí)器,達(dá)到準(zhǔn)確控制時(shí)間的目的2022-08-08
java使用udp實(shí)現(xiàn)簡(jiǎn)單多人聊天功能
這篇文章主要為大家詳細(xì)介紹了java使用udp實(shí)現(xiàn)簡(jiǎn)單多人聊天功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
SpringBoot多模塊項(xiàng)目創(chuàng)建和初始化問題
本文詳細(xì)介紹了使用SpringBoot框架創(chuàng)建一個(gè)包含數(shù)據(jù)庫操作、MyBatis-Plus、Knife4j、HTTP請(qǐng)求響應(yīng)等的Java Web項(xiàng)目的步驟和配置方法,內(nèi)容涵蓋創(chuàng)建項(xiàng)目結(jié)構(gòu)、配置數(shù)據(jù)庫連接、添加依賴、編寫接口、處理異常、序列化和反序列化、配置接口文檔等等內(nèi)容2026-05-05
java使用單向鏈表解決數(shù)據(jù)存儲(chǔ)自定義排序問題
本文主要介紹了java使用單向鏈表解決數(shù)據(jù)存儲(chǔ)自定義排序問題,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Spring Security OAuth2集成短信驗(yàn)證碼登錄以及第三方登錄
這篇文章主要介紹了Spring Security OAuth2集成短信驗(yàn)證碼登錄以及第三方登錄,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04
SpringBoot整合MongoDB的實(shí)現(xiàn)代碼
自己本科時(shí)候一直使用的是Mysql,目前的課題組使用的是MongoDB,因此就花了一部分時(shí)間整理了一下,實(shí)現(xiàn)springboot與MongoDB的整合,并且實(shí)現(xiàn)基本的增刪改查操作,從頭到尾給出一個(gè)完整的案例。2021-05-05

