blog

PowerJob의 UseCacheLock에 대해 이야기하기

시퀀스 이 문서에서는 PowerJob의 UseCac에 중점을 둡니다....

Oct 12, 2025 · 3 min. read
シェア

시퀀스

이 문서에서는 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 어노테이션은 유형, 키 및 통화 수준 속성을 정의합니다.

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();
 }
 }
}

예시

@UseCacheLock(type = "processJobInstance", key = "#instanceId", concurrencyLevel = 1024) public void redispatchAsync(Long instanceId, int originStatus) { // 상태를 디스패치 대기 중으로 재설정 instanceInfoRepository.updateStatusAndGmtModifiedByInstanceIdAndOriginStatus(instanceId, originStatus, InstanceStatus.WAITING_DISPATCH.getV(), new Date()); }

keySpEl 지원

Read next

vue2 모바일 웹 페이지 이미지 슬라이드를 터치하여 상단과 왼쪽 및 두 손가락 줌 이미지를 변경합니다.

코드 렌더링 두 손가락 줌 두 손가락 줌 위의 코드를 복사하여 vue2 페이지에 직접 붙여넣고 이미지 주소를 수정하여 사용할 수 있습니다.

Oct 11, 2025 · 3 min read