JAVA/프로젝트

쿠폰 선착순 발급 이벤트 - redis 분산락 쿠폰 발급 문제점.

whyHbr 2024. 12. 5. 23:33
728x90
반응형

redis 분산락을 적용 사용해 쿠폰 발급 처리하는 로직을 작성했는데, RPS 가 낮다.

 

 

public void issue(long couponId, long userId) {
    //쿠폰 캐시를 통한 유효성 검증을 캐시 처리. 엔티티 필드를 가져오는 부분을 캐시 처리
    CouponRedisEntity coupon = couponCacheService.getCouponCache(couponId);
    //캐시로 날짜 유효성 검사
    coupon.checkIssuableCoupon();
    Integer totalQuantity = coupon.totalQuantity();
    //동시성 제어를 위한 락
    distributeLockExecutor.execute("lock_%s".formatted(couponId), 3000, 3000, () -> {
        //수량 검증
        couponIssueRedisService.checkCouponIssueQuantity(coupon, userId);
        //쿠폰 발급 queue 에 적재
        issueRequest(couponId, userId);
    });
}

 

코드에서 락 부분이 성능 저하를 일으킨다.

 

 

락 제거를 하고 테스트를 하니 RPS는 상승했으나

 

300개만 발급 되어야 할 쿠폰이 325 개가 들어와있다. 

 

 

/*
락에서 하는 것
1. 쿠폰 수량 제어: totalQuantity > redisRepository.sCard(key);
2. 중복 발급 요청 제어:  !redisRepository.sIsMember(key, String.valueOf(userId));
3. 쿠폰 발급 요청 저장: redisRepository.sAdd
4. 쿠폰 발급 큐에 적재: redisRepository.rPush
 */

이 모든 과정을 하나로 묶어 레디스에 단일 command 로 처리하길 원함.

-> redis script https://redis.io/docs/latest/commands/eval/

 

EVAL

Executes a server-side Lua script.

redis.io

4개의 과정을 script를 담아둔다. 

레디스는 싱글 스레드로 실행이 되어, 스크립트가 실행되는 동안 다른 요청을 수행할 수 없다. -> 동시성 이슈 해결이 가능하다. 

 

728x90