소개
안녕하세요. 지식공유자 최상용입니다.
많은 오픈소스에 기여한 경험이 있는 현직 백엔드 개발자입니다.
- Spring Data Mongo Contributor
- querydsl Contributor
- grpc-kotlin Contributor
- ksp Contributor
- mybatis Contributor
강의
수강평
- 재고시스템으로 알아보는 동시성이슈 해결방법
- 재고시스템으로 알아보는 동시성이슈 해결방법
게시글
질문&답변
ApplyService 의 총 처리 시간이 궁금합니다.
조기윤님 안녕하세요.Thread 1 에서 10:00 에서 10:02 동안 incr coupon_count 메서드가 동작한다고 했을 때 10:02분에 끝나고나서 thread 2의 incr coupon_count 가 동작한다고 말씀하셨는데요이는 딱 redis 가 싱글스레드로 동작하는 시간 만큼만이 lock 이 걸린 시간이라고 보면 될까요?여기서 lock 은 어떤 lock 을 말씀하시는걸까요?강의에서 말하고자 했던것은 redis 는 순차적으로 명령을 실행하며 현재 실행중인 명령이 끝나야 다음 명령이 실행된다 였습니다!예컨데 ApplyService 의 apply 가 싱글 스레드, 단일 요청에 딱 2분이 걸리는 메서드라고 가정하고 그 안에 있는 couponCountRepository.increment() 가 1초가 걸린다고 가정하면 100개의 요청이 동시에 들어온 경우, 전체 요청이 모두 처리되는 시간이 2분 + 1*100초 = 3분 40초가 걸린다고 계산하는게 맞는거죠? 2분*100이 아니라요ApplyService.apply 메소드가 싱글스레드로 동작하며 메소드의 실행시간이 2분이라고 가정하고couponCountRepository.increment() 가 1초가 걸린다고 가정한다면100개의 요청을 처리하는데 걸리는 시간은 2분 * 100 일것같네요.ApplyService.apply 는 1번에 1개의 요청밖에 처리를 하지 못합니다. couponCountRepository.increment() 하는 로직은 ApplyService.apply 메소드 안에 존재합니다.ApplyService.apply 는 처리하는데 2분이 걸립니다. 싱글스레드 이므로 이전 요청이 끝나고난 이후 다음 요청을 처리할 수 있습니다. 따라서 100개의 요청을 처리하는데는 2 * 100 분이 걸릴것같네요
- 0
- 1
- 17
질문&답변
오류?
alpacaive 님 안녕하세요.히카리 설정이 무언가 안되있는듯해보입니다.강의실습을 하는데 문제가 없다면 일단은 넘어가도 될것같고, 문제가 있어서 진행이 되지않는다면 해당 소스를 깃에 올려주신 후, 사용하고 계시는 mysql 버전을 말씀해주신다면 봐보도록 하겠습니다!
- 0
- 2
- 247
질문&답변
쿠폰 생성 에러 처리에 관해서 질문이 있습니다.
홍혁준님 안녕하세요.해당건은 정책에 따라 다를것 같으며 구현방법은 여러가지가 있을것 같습니다.말씀해주신대로 try catch 와 같은것을 사용하여 실패시 redis 에 있는값을 줄이는 방법이 있을수 있을것 같습니다.다른 방법으로는 발송에 실패한 유저들을 따로 저장해두었다가 쿠폰발급을 해줄수도 있을것 같습니다.감사합니다.
- 0
- 2
- 71
질문&답변
마지막에 하신 테스트 자체는 실패하는 게 맞는거죠??
0515 님 안녕하세요!뒷강의까지 진행하셨을때도 해결이 안되셨을까요?테스트에 실패하는 이유와 간단하게 확인할 수 있는 방법이 강의 후반에 나와서요!
- 0
- 2
- 67
질문&답변
안녕하세요 질문 있습니다!
감바스님 안녕하세요.답변이 너무 늦어져서 죄송합니다.현재 카프카로 데이터를 보내기전에 redis를 사용하여 발급된 쿠폰 개수에 대한 동시성 처리를 해서 개수에 대한 검증 로직이 있다고 앞서 강의에서 얘기를 하셨습니다. 그러면 발급된 쿠폰 개수가 100개 되고 난 이후의 요청은 그냥 무시하면 되나요?Application 에서 무시여부를 여쭤보신거라면 발급불가라고 응답을 하면 될것 같습니다.예를들어 "이미 모두 소진되었어요" 라는 메시지를 내려줄 수도 있을것 같습니다.Consumer 에서 무시여부를 여쭤보신거라면 요청이 100개가 넘게 온 상황은 비즈니스 로직에서 구멍이 생긴것이며 문제가 있는 상황일겁니다.이런상황에서는 에러를 발생시켜 개발자가 인지하도록 해야할듯합니다.쿠폰이 천개, 만개 이렇게 매우 많다면 쿠폰 발급에 대한 요청을 바로 DB에 저장을 하면 DB에 부하가 심해져서 카프카를 도입해 이러한 부하를 낮춘다고 이해를 했습니다. 궁금한 점은 DB에 대한 부하를 낮춰도 이벤트 시기에 수많은 사용자들의 요청으로 인해 서버 자체에 대한 부하는 굉장히 심할꺼 같은데 서버에 대한 부하를 낮추는 방법은 없나요?이것은 인기가 많은 콘서트나 스포츠경기를 예매하는것을 떠올려보시면 힌트를 얻으실 수 있습니다!서버에 요청을 보낼 수 있는 일정수만을 통과하기 위해 대기열을 만들고 순서가 되었을때만 서버에 요청을 보낼 수 있도록 하면 됩니다.콘서트를 예매할 때 대기번호 102번 이런식으로 받고 기다리다가 순서가되면 예매를 시도하는것을 확인하실 수 있을겁니다!현재 흐름이 쿠폰 요청 -> 서버 -> reids에서 쿠폰 개수 확인 -> 카프카 -> 컨슈머 -> DB 인데 이러한 흐름을 요청 -> 서버 -> 카프카 -> 컨슈머 -> redis에서 쿠폰 개수 확인 -> DB 이렇게 바꾸는 방식은 어떤지 궁금합니다. 이런식으로 하면 서버쪽에서 카프카로 데이터를 비동기로 전송한다면 서버 자체에도 부하가 낮아지지 않을까 라는 생각이 들어서 여쭤 봅니다.말씀해주신대로 변경을 하게되면 소비자는 쿠폰이 발급이 되었는지 여부를 확인할 수 없는 문제가 있습니다!redis streams나 래빗엠큐 같은 다른 기능들도 있는데 Kafka를 사용하신 이유가 궁금합니다.대중적으로 사용되는 기술이 kafka 여서 강의에서 사용하기로 결정하였습니다.말씀해주신 redis streams, 래빗엠큐 같은 대안도 존재할 수 있습니다.각자의 특징이 있고 해당기술들이 알맞는 상황들이 있으니 알맞게 사용하는것이 중요할것 같습니다.만약 쿠폰 발급이 100개처럼 적게 발급하는 시스템이라면 굳이 카프카를 도입을 할 필요가 없는건가요?kafka 를 사용한 이유는 처리량을 제어하여 DB 의 부하를 줄이기 위하여 사용하였습니다.DB 에 부하가 가지 않는 상황에서는 굳이 사용하지 않아도 됩니다.publisher가 카프카로 데이터를 보내면 consumer가 바로 받아와서 DB에 처리를 하면 안되겠죠? 이렇게 처리를 하면 바로 DB에 저장을 하는 상황이니 DB에 부하가 심해진다고 생각합니다.consumer 는 메시지를 큐에 저장해놓고 순차적으로 가져와서 처리를 하게됩니다.그렇기때문에 100개의 요청이 들어온다고 하여도 1개의 요청을 끝내고 다음 요청을 가지고 와서 처리를 하게됩니다. (물론 파티션 개수와 컨슈머의 개수에 따라 동시에 n개의 요청이 처리될 수 있습니다. 이 부분은 kafka 를 공부해보시면 좋을것같아요!)그렇기때문에 바로 consumer 에서 바로 받아와서 DB 에 처리를 해도 될것이라고 생각됩니다.100개가 아닌 무수히 많은 쿠폰이라면 replication 지연이 일어날 수 있으므로 consumer 에서 Thread.sleep 을 이용하여 일부 요청간의 delay 를 주어 제어하는 방법도 있습니다.현재 강사님이 알려주신 코드를 바탕으로 시스템을 구축하고 여기에 부하 테스트를 한다고 했을때 어떤 식으로 단계를 잡아서 부하 테스트를 하면 좋을지 조언을 해주실 수 있을까요 만약 제가 시스템을 구축한다고 가정한다면 아래의 순서대로 할것같습니다.consumer 가 존재하지 않는 상태로 1대의 서버가 동시에 처리 가능한 요청이 얼마인지 알아보기 위해 부하테스트를 진행할듯합니다. -> 이때 1000개의 요청이 max, DB 에는 부하가 없다고 가정해보겠습니다.그 후 DB 는 어느정도의 요청까지 버틸 수 있는지 판단하기 위하여 서버를 여러대로 늘려 부하테스트를 진행 해볼것같습니다.세번째로 redis 가 어디까지 버틸 수 있는지 판단하기 위하여 서버를 여러대 늘려서 해볼것 같습니다. 1~2번을 통하여 얻을 수 있는것은 현재 예상되는 트래픽을 버티려면 몇대의 서버가 필요한지, DB 가 버틸 수 있는지를 알아볼 수 있을것이고 DB 가 버틸 수 있다면 kafka 를 도입하지 않고, 버틸 수 없다면 kafka 와 같은것을 도입할 것 같습니다.3번을 통하여 얻을 수 있는것은 동시에 몇개의 요청까지 수용할 수 있는지? 이며 2번 질문에 대한 답변과 같은 대기열을 추가 구현해야할지에 대한 판단을 할 수 있을것 같습니다. 답변을 늦게드린점 다시한번 사과드리며 좋은질문들 남겨주셔서 감사합니다.
- 0
- 1
- 125
질문&답변
LettureLockStockFacadeTest에서 오류가 발생합니다.
소리쨩님 안녕하세요.첫번째로 강의에 첨부드린 github 에 있는 소스로 해도 테스트가 통과하지 않는지 궁금합니다.두번째로 테스트가 통과하지 않는 소스코드를 github 에 업로드 해주시고 주소를 공유해주실 수 있으실까요?디버깅을 해보면 좋을거같습니다
- 0
- 2
- 66
질문&답변
Pessimistic Lock 전체 테스트 오류 문의
HeeSeok Noh 님 안녕하세요.1) 데이터베이스의 설정이 auto_increment 로 되어있기때문에 그럴겁니다.2) 테스트를 시작하기전에 findByFirst 를 하여 id 를 얻어온 후 그 값을 사용하면 될것같습니다.감사합니다.
- 0
- 3
- 118
질문&답변
비관적 락 vs 레디스(Lettuce)락 비교 관련 질문
현이님 안녕하세요.일단 테스트환경마다 어떤것이 더 적합한지는 다르다라고 말씀을 드릴 수 있을것 같습니다.그렇기때문에 어떤방법이 무조건 더 좋다가 아닌 상황별로 좋은 방법은 다르다라고 이해해주시면 좋을것 같습니다.1개의 테이블만 접근하는것이 아닌 여러개의 테이블에 접근하고 스레드가 많은 상황에서 모든 테이블에 락을 걸게된다면 데드락이 발생할 확률이 높아질것입니다. 이러한 경우에 redis 를 활용한 lock 이 효율적일 수 있을것 같습니다.이부분은 어떤부분이 궁금하신것인지 조금만 더 자세하게 질문해주실 수 있으실까요?이 부분도 상황마다 다릅니다. 각자의 데이터베이스에서 락을 거는것이 효율적일 수 있고 redis 를 사용하여 락을 제어하는것이 효율적일때가 있을 수 있을것 같습니다. 예를들어 결제를 위해 포인트도 사용해야하고 카드도 결제해야 하는 상황이있고 MSA 로 구성이 되어있는경우 "결제 API" 에 동시에 1개의 요청만 오도록 하는것이 합리적일것입니다. 이때 각 DB 에 락을 거는것으로는 해결하기 힘드므로 redis 를 활용하여 사용할 수 있을것 같습니다.감사합니다.
- 0
- 2
- 195
질문&답변
낙관적락 vs 네임드락
gelab 님 안녕하세요.답변이 늦어져서 죄송합니다.네임드락의 경우 락을 다른 세션에서 점유하고 있을 때 일정시간 기다릴 수 있는 기능이 있습니다.이로 인해 대부분의 경우 별도의 재시도 로직은 필요없을것이라고 생각됩니다.일정시간 이상 기다렸는데도 실패했을때 다시 시도하기를 원한다면 재시도로직을 작성할수도 있을것 같습니다.감사합니다.
- 0
- 2
- 164
질문&답변
동시성 문제 해결방안
gelab 님 안녕하세요!말씀하신대로 native query 를 사용해서 해결할수도 있습니다.다만, native query 를 사용할때는 아래와 같은 조건으로 해야할것 같습니다.@Query("UPDATE Stock s SET s.quantity = s.quantity - :quantity WHERE s.id = :id and (s.quantity - :quantity) >= 0")또한, 이 강의는 동시성이라는 주제를 다루기위하여 "재고" 라는 아이템을 선택한것이지 "재고"를 다루려면 무조건 lock 을 잡아야한다는 아니었습니다!감사합니다.
- 0
- 2
- 116