<aside> 💡 pub-sub방식을 활용하여 Java에서 사용되는 Redis 클라이언트
</aside>
Lettuce와 다르게 Lock을 획득하지 못했을 때 재시도 횟수가 적어서 Redis에 부하가 적음
Lock 관련 Class를 따로 제공 ⇒ Rlock 제공 ⇒ 별도로 class를 만들 필요가 없다.
Pub-sub방식
로직 실행 전후로 Lock 획득, 해제 해주는 Class가 필요
⇒ 채널을 하나 만들고, Lock을 점유 중인 스레드가 Lock을 해제했음을 대기중인 스레드에게 알려주면, 대기중인 스레드가 Lock 점유를 시도하는 방식
Redisson 전체 코드
Redisson를 위한 implementation을 추가
//Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
//redisson
implementation group: 'org.redisson', name: 'redisson-spring-boot-starter', version: '3.23.1'
Redisson을 활용한 서비스 코드 작성
카카오페이 로직 중 결제 준비
이후, 결제 승인 요청
단계부터 redisson을 활용한 lock 처리 진행
@Override
@Transactional
public PaymentSuccessResponse approvePaymentWithLock(String pgToken) {
Long memberId = securityUtil.getCurrentMemberId();
String key = REDIS_CACHE_KEY_PREFIX + memberId;
PaymentRedisDto paymentInfo = getPaymentInfo(key);
RLock lock = redissonClient.getLock(REDIS_LOCK_KEY_PREFIX + paymentInfo.productId());
try {
if (!lock.tryLock(500, 5_000, TimeUnit.MICROSECONDS)) {
throw new RuntimeException();
}
Product targetProduct = productRepository.findById(paymentInfo.productId())
.orElseThrow();
checkOutOfStock(targetProduct);
return approvePayment(pgToken, memberId);
} catch (InterruptedException e) {
throw new RuntimeException();
} finally {
if (lock != null && lock.isLocked()) {
lock.unlock();
}
}
}
RLock lock = redissonClient.getLock();
key이름에 해당하는 RLock 인스턴스를 가져온다
(Redisson에서 lock을 사용하기 위해 Rlock 인터페이스 제공)
boolean lock.tryLock(long waitTime, long leaseTime, TimeUnit unit)
여러 Thread를 동시에 요청하기 위해, Jmeter를 사용했습니다.
Thread를 100개로 10초 안에 수행되도록 진행했습니다 (1개의 Thread가 0.1초 안에 실행)