728x90
problem
DB 동시성제어 (PessimisticLock) : https://soobysu.tistory.com/127
이전 글에서는 db의 PessimisticLock을 사용하여 공유자원에 대한 동시성 문제를 해결 했다.
이번 글에서는 레디스를 이용해 분산락을 사용하여 동시성 문제를 해결 하고자 한다.
solution
분산락은 분산시스템으로 부터 들어오는 공유자원의 데이터의 무결성을 위해 임계영역을 보호한다.
// 비즈니스 로직
@RequiredArgsConstructor
@Service
public class ReviewService {
private final RedissonClient redissonClient;
@Transactional
public void couponIssuance throws(RequestDto requestDto) {
RLock isLock = redissonClient.getLock("key 이름");
try {
boolean isLocked = lock.tryLock(2, 3, TimeUnit.SECONDS);
if (!isLocked) {
// 락 획득에 실패했을때 처리 ex)예외 처리
throw new Error( ... );
}
//로직 수행
couponIssuance(requestDto)
} catch (InterruptedException e) {
// 쓰레드가 인터럽트 될 경우의 예외 처리
} finally {
// 락 해제
lock.unlock();
}
}
}
Redisson의 RLock을 생성하고 작업을 수행 후 락을 해제한다.
1 ) lock.tryLock(락을 얻기 위한 대기시간 , 락 사용시간, 시간의 단위들);
락 사용시간을 설정하여 데드락 방지
tryLock의 첫번째 파라미터로 락 획득을 대기할 시간을, 두번째 파라미터로 락이 만료되는 시간을 설정한다.
2초 동안 락을 획득하지 못하면 false를 반환하여 락 획득을 실패했음을 알려주고, 락을 획득하고 나서 3초가 지나면 자동으로 레디스에 저장된 key:value가 삭제되기 때문에 기타 상황들에 의해 락이 해제되지 않더라도 다른 스레드에서 락을 획득할 수 있게 해준다
Radisson 은 실제로 pub/sub 구조로 구현이 되어있어 tryLock을 기준으로 구독을 시작하고 락이 해제되면 다음 쓰레드에게 락 획득을 알려주어 Lettuce 처럼 polling 요청을 하지 않아도 된다.
아래는 실제 radisson tryLock 구현코드 이다
@Override
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
long time = unit.toMillis(waitTime);
long current = System.currentTimeMillis();
long threadId = Thread.currentThread().getId();
Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
// lock acquired
if (ttl == null) {
return true;
}
time -= System.currentTimeMillis() - current;
if (time <= 0) {
acquireFailed(waitTime, unit, threadId);
return false;
}
current = System.currentTimeMillis();
//스레드id를 기반으로 CompletableFuture 로 subscribe 수행한다
CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
728x90
'개-발 > Infra' 카테고리의 다른 글
[ElasticSearch] SpringBoot 3.x elasticsearch 8.x 연동 ( with.Kotlin ) (0) | 2024.05.06 |
---|---|
[ElsticSearch] 엘라스틱서치 개념과 Query (0) | 2024.04.09 |
[Kafka] MSA 서버간 비동기 통신 (요청 - 응답 모델) (0) | 2024.02.29 |
[Kafka + SSE] 실시간 알림 메세지 구현 (0) | 2024.01.10 |
[Docker + NginX + Jenkins] Jenkins pipline verbose 옵션 CICD번외 편 (0) | 2023.12.13 |