Redisson Client Lock
public void buy(String ticketName) throws InterruptedException {
RLock lock = redissonClient.getLock(ticketName);
try {
boolean available = lock.tryLock(5, 1, TimeUnit.SECONDS);
if (!available) {
return;
}
ticketServiceWithRedisRedissonClientLock.buy(ticketName);
} finally {
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}이 구조에서 tryLock에 대해서 5초동안 Lock 획득을 위해서 대기하고 Lock을 1초동안 점유하고 release하는 형식으로 알고있는데 만약에 쓰레드가 5초 동안 대기를 하더라도 최종적으로 Lock을 얻지 못한다면 return이 됨으로써 buy로직으로 못들어가는거 아닌가요??
만약에 반드시 Lock을 얻고 buy로 들어가야만 하는 경우 Lock 재획득에 대한 로직을 따로 구현해야 하는건가요. 아니면 tryLock의 재시도에 대해서 제가 모르는 부분이 있는건가요??
public void buy(String ticketName) throws InterruptedException {
final RLock lock = redissonClient.getLock(ticketName);
final int maxRetryCount = 10;
final int retryIntervalMillis = 1000;
try {
int retryCount = 0;
boolean lockAcquired = lock.tryLock(5, 1, TimeUnit.SECONDS);
while (!lockAcquired && retryCount < maxRetryCount) {
log.info(
"--> Thread [{}] Redis Distributed Lock (Redisson Client) 획득 대기",
Thread.currentThread().getName()
);
Thread.sleep(retryIntervalMillis);
lockAcquired = lock.tryLock(5, 1, TimeUnit.SECONDS);
retryCount++;
}
if (!lockAcquired) {
log.info(
"--> Thread [{}] Redis Distributed Lock (Redisson Client) 획득 실패",
Thread.currentThread().getName()
);
return;
}
ticketServiceWithRedisRedissonClientLock.buy(ticketName);
} finally {
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}이런 방식으로 최대 재시도 횟수와 재시도 간 간격을 통해서 waitTime동안 Lock을 못얻을 경우 Lock자체를 다시 얻는 방식을 구현해보았고 waitTime=1, unit=ms로 변경하고 테스트했을 경우 정상적으로 retry가 됨을 확인했습니다.
이런 구조가 최선일까요??
아니면 더 나은 방식이 있을까요?
답변 2
1
avenue 님 안녕하세요.
말씀하신 내용과 같이 waitTime 만큼 기다렸다가 획득에 실패하면 return 을 하게됩니다.
무조건 획득을 해야하는 방식이라면 avenue 님께서 말씀해주신 방법대로 진행을 할 것 같습니다.
감사합니다.
0
안녕하세요, 인프런 AI 인턴이에요.
tryLock 메소드는 매개변수로 받은 대기 시간 안에 Lock을 획득할 수 없다면 false를 반환하여 리턴합니다. 그렇다면 buy 메소드에서 lock.tryLock(5, 1, TimeUnit.SECONDS) 대기 시간이 5초이므로 5초 안에 Lock을 획득하지 못하면 false를 반환합니다. 이 경우 buy 메소드에서는 해당 티켓에 대한 Lock을 획득하지 못하게 되어 ticketServiceWithRedisRedissonClientLock.buy 메소드를 실행하지 않고 바로 return을 하게 됩니다.
만약에 반드시 Lock을 얻고 buy 메소드 실행이 필요하다면, retry 로직을 추가하여 Lock 획득이 가능할 때까지 tryLock 메소드를 반복 호출하는 방식으로 처리할 수 있습니다. 물론 이 경우에도 최대 대기 시간과 재시도 시간 등을 고려하여 구현해야 합니다.
참고로 Redisson의 RLock 객체는 Redis에서 제공하는 분산 Locking 기능을 사용하므로, 여러 인스턴스에서 동시에 사용해도 정확하게 Locking이 동작합니다.
도움이 되었길 바랍니다. 감사해요 :)
레디선 테스트코드에서 채널이름은 없어도 되는건가요?
0
43
2
낙관적 락을 사용할 떄 차이점
0
123
2
동시성 검증 코드에 관한 문의
0
96
2
단일연산
0
70
2
낙관적락vs. 레디스락
0
108
2
안녕하세요. 레디슨 질문있습니다..!!
0
67
2
@Lock(OPTIMISTIC)이 필요한 이유
0
90
2
get_lock 의 timeout이 3000초 이던데 너무 긴거 아닌가요?
0
132
2
DataSource Hikari 사용 이유
0
147
2
saveAndFlush 사용 이유 문의
0
113
3
비관적 락 VS 네임드 락
0
160
3
application.yaml 에 redis 정보
0
100
2
왜 클래스 이름에 Facade 가 붙나요?
0
185
2
@Transactional 으로 인한 동시성 문제 발생 원인이 궁금합니다.
0
220
2
@modifying 이용한 동시성 제어
0
168
2
DB락과 분산락
0
262
2
NamedLock 테스트 실패
0
186
2
테스트에서 트랜잭션 어노테이션 질문 있습니다.
0
173
2
optimistic Lock 재시도 질문입니다.
0
232
2
낙관적 락 테스트 실패
0
242
2
오류?
0
1627
4
LettureLockStockFacadeTest에서 오류가 발생합니다.
1
268
2
Pessimistic Lock 전체 테스트 오류 문의
0
361
3
비관적 락 vs 레디스(Lettuce)락 비교 관련 질문
0
461
2





