inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

실습으로 배우는 선착순 이벤트 시스템

문제점 해결하기

왜 쿠폰수가 너무 많을까요?

633

seonjun Moon

작성한 질문수 35

0

분명 현재 없는 상태이고

결과가 자꾸 이상하게 나와서 sout 처리를 잠시 해보았습니다

 

package com.example.api.service;

import com.example.api.domain.Coupon;
import com.example.api.repository.CouponCountRepository;
import com.example.api.repository.CouponRepository;
import org.springframework.stereotype.Service;

@Service
public class ApplyService {

    private final CouponRepository couponRepository;
    private final CouponCountRepository couponCountRepository;

    public ApplyService(CouponRepository couponRepository, CouponCountRepository couponCountRepository) {
        this.couponRepository = couponRepository;
        this.couponCountRepository = couponCountRepository;
    }

    public void applyV1(Long userId) {
        Long count = couponRepository.count();

        if(count > 100) {
            return;
        }

        couponRepository.save(new Coupon(userId));
    }

    public void applyV2(Long userId) {
        Long count = couponCountRepository.increment();
        System.out.println(count);

        if(count > 100) {
            return;
        }

        couponRepository.save(new Coupon(userId));
    }

}

 

@SpringBootTest
class ApplyServiceTest {

    @Autowired
    private ApplyService applyService;

    @Autowired
    private CouponRepository couponRepository;

    @Test
    public void applyOnce() {
        applyService.applyV1(1L);

        long count = couponRepository.count();
        Assertions.assertEquals(1L, count);
    }

    @Test
    public void 여러명응모V1() throws InterruptedException {
        int threadCount = 1000;
        ExecutorService executorService = Executors.newFixedThreadPool(32);
        CountDownLatch latch = new CountDownLatch(threadCount);

        for(int i=0; i<threadCount; i++){
            long userId = i;
            executorService.submit(() -> {
                try {
                    applyService.applyV1(userId);
                } catch(Exception e) {
                    System.out.println(e);
                }finally {
                    latch.countDown();
                }
            });
        }
        latch.await();

        long count = couponRepository.count();

        assertThat(count).isEqualTo(100);
    }

    @Test
    public void 여러명응모V2() throws InterruptedException {
        int threadCount = 1000;
        ExecutorService executorService = Executors.newFixedThreadPool(32);
        CountDownLatch latch = new CountDownLatch(threadCount);

        for(int i=0; i<threadCount; i++){
            long userId = i;
            executorService.submit(() -> {
                try {
                    applyService.applyV2(userId);
                } catch(Exception e) {
                    System.out.println(e);
                }finally {
                    latch.countDown();
                }
            });
        }
        latch.await();

        long count = couponRepository.count();

        org.assertj.core.api.Assertions.assertThat(count).isEqualTo(100);
    }

}

 

그런데 여러명응모V2 test를 실행시에 count를 출력시

다음과 같은 수가 나옵니다.

 

20003

20011

20012

20013

20015

20016

20017

20018

20020

20022

 

???

 

한번 할때마다 1000씩 쿠폰의 수가 증가중인데요;;;

조회했을때는 empty라 나오는데 이렇게 되는 연유를 잘 모르갰습니다.

 

테스트 코드라서 rollback이 되야할거 같은데 그렇지 않는것도 잘 모르겟네요;; ㅠㅠ

java docker spring-boot kafka redis

답변 1

2

최상용

seonjun Moon 님 안녕하세요.
강의내용과 동일하다면 CouponCountRepository 는 redis 를 사용하는 Repository 로 보입니다.
이 Repository 의 increment 는 현재 쿠폰의 개수와는 상관없이 1개를 증가시키는 로직을 가지고 있습니다.
그리고 증가시킨 쿠폰의 개수가 100 개보다 많다면 쿠폰을 발급하지 않는것은 ApplyService 에서 담당하고 있습니다.
즉 현재 출력되는 것은 정확하게 말씀드리면 "현재 발급된 쿠폰의 개수" 보다는 "쿠폰을 발급요청한 요청의 수" 기때문에 출력되는 숫자가 많은것이 맞습니다.
숫자가 초기화가 되지 않는이유는 redis 는 테스트케이스를 실행시킬때마다 초기화가 되지 않기때문입니다.
이를 자동으로 초기화를 시키려면 beforeAfter 를 이용하여 테스트케이스가 실행된 후에 Redis 의 값을 초기화 해주시면 됩니다.
감사합니다 :)

0

seonjun Moon

답변 감사합니다 :) 밤늦게 고생하시네요 ㅠㅠ

ApplyService와 Consumer서비스의 db공유?

0

55

2

consumer가 topic을 전부 사용하기 전에 사용자에게는 쿠폰이 발급된것으로 확인하는 과정에서 발생가능한 문제.

0

76

1

쿠폰에 관련되어서 좀 더 참고할만한 자료가 있을까요?

0

85

2

흐름정리 제가 이해한게 맞나요?

0

73

2

안되서 스트레스 받아요

-2

109

2

프로젝트 진행할때 모듈로 추가하는 이유가 궁금합니다!

0

183

2

Redis 활용하기 문제점 해결하기 부분이 이해가 잘 안됩니다...

0

213

1

카프카를 도입하고 난 뒤 로그로 보여지는 장점을 발견하지 못하고 있습니다.

0

167

2

키생성 방식에 따른 성능

0

167

2

사용자 동선에 대한 트랜잭션 문의

0

134

2

강사님 강의를 듣고 실제 프로젝트에서 이벤트 응모 시스템을 만들어 봤습니다.

0

210

1

쿠폰 발급 개수 제한

0

183

2

ApplyService 의 총 처리 시간이 궁금합니다.

0

154

1

쿠폰 생성 에러 처리에 관해서 질문이 있습니다.

0

224

2

마지막에 하신 테스트 자체는 실패하는 게 맞는거죠??

0

276

2

안녕하세요 질문 있습니다!

0

294

1

쿠폰 발급 유저 흐름에 대한 질문

0

308

2

수량 조절에 대한 질문이 있습니다.

0

230

2

kafka Producer 실행 중 에러 시 redis count 정합성 이슈

0

398

2

test 과정에서 오류가 발생합니다.

0

383

1

도커 환경설정에 대해서

0

269

2

Redis의 INCR 사용 해도 Race condition이 잡히지 않는 문제

0

597

1

consumer 모듈

0

322

2

카프카 토픽 생성오류

0

383

2