Search
📚

AWS KRUG - ECS, Amazon MQ를 이용한 선착순 쿠폰 발급 개선

1. 발표 내용 정리

1.1. 현황

세일
1년에 4번
매일 00시, 12시 선착순 쿠폰 발급
해당 시간대 트래픽 발생
대기열 발생으로 고객 경험 저하

1.2. 기존 쿠폰 발급 프로세스

프로세스
1.
쿠폰 발급 요청 (FE)
2.
쿠폰 발급 처리 요청 (BE)
3.
쿠폰 발급 유효성 검사 (RDB)
실패
고객에게 Fail 응답 Return
성공
발급 기록 → 발급 처리
모든 로직이 synchronized하게 동작
경합, Lock, 멀티스레드 이슈 등…

1.3. 개선 쿠폰 발급 프로세스

프로세스
기본 Flow
온라인몰(BE) → Elasticache → Amazon MQ → Worker → DB
유효성 검사 (수량 등)
1차 유효성 검사 (Elasticache)
2차 유효성 검사 (Amazon MQ)
worker에서 데이터를 DB에 저장
고객 경험
고객은 서버의 응답을 기다리는게 아니라, 먼저 정상 응답을 받고, 백그라운드에서 워커로 로직 처리
리다이렉트로 웹사이트에서 서핑하는 도중에 이미 쿠폰 발급 로직이 백그라운드에서 완료
MQ 대안들에 대한 코멘트
Redis PubSub
최초에 사용했으나 이슈 발생 (어떤 이슈였는지는 듣지 못함)
SQS
큐 타입에 따라 중복 수신이 되는 경우도 있음
이걸 처리하려면 TPS가 늦어지는 케이스도 발견
MSK
특성상 맞지 않았음
토픽에 대해 파티셔닝하여 처리
파티셔닝이 늘어나면 큐를 삭제하지않고서는 줄이기 힘듬
트래픽에 따라 워커를 늘려야하는데 이게 적절하지 않았음

1.4. 결과

개선 이후 직전 3월 세일 대비 발급 성능 2배로 향상되었음

1.5. 질의 응답

워커가 많이 늘어나면? DB 부하 늘어날것같은데 어떻게 했는지? DB Write 사이즈는?
가장 클때를 기준으로 설정
오라클 DB 1대, 큰 문제는 없었다…
워커 발급 실패한 경우?
개선된 프로세스로는 실패 0건이었음
lambda 도 괜찮아 보이는데 워커를 ECS를 사용한 이유는?
람다는 warm up 올라오는 시간이 걸림
한번 올라온 상태에서 꾸준히 발급하길 원해서 ECS를 사용
MQ에서 람다를 호출하는 게 리스너 연결해서 다시 호출하거나 해야하는데.. 다이렉트로 MQ에서 받는걸로 설정
EC2 도커 Rabbit MQ도 괜찮았는데, Amazon MQ를 사용한 이유는?
유실 가능성 있는 경우 → 클러스터 구성 필요
이때, Managed 서비스로 클러스터 구성하는게 훨씬 나았음
스트레스 테스트
유사한 환경으로 50번 정도 테스트
어느시점에 발급되었습니다 리턴?
첫번째 유효성 통과했을때(ElastiCache) 발급 완료 통보
선착순 몇명까지 쿠폰을주는지? 예를 들어 1만명한테 쿠폰을 준다면 1만 3번째 유저는 어떻게 처리?
1만번 발급 → 워커에서 엘라스틱 캐시로 데이터 업데이트
이후 1만3번째 유저가 조회한다면 엘라스틱 캐시에서 유효성검증실패로 발급 실패
중복 요청
Global Lock , 동일한 요청은 3초간 잠금
엘라스틱 캐시 요청 집중이 되더라도 시간복잡도 O(1)이라 문제 없었다
순간적으로 사용자 몰렸을 때(온라인몰 → MQ 커넥션 몰릴때) - producing 많아지는 경우
MSK → 컨슈머 워커 늘리는것에도 이슈
Rabbit MQ(Amazon MQ) → 얼랭으로 구현되어있음 → 고속 성능 고려
워커에서 실패하는 경우는 없었는지?
없었다. MQ에 DLQ가 존재함. 워커가 복구하면 처리할 것으로 기대함
ECS 구성할 때, 예상 사용 트래픽 감안하여 스케일 설정 했는지?
큐의 잔존 메세지 수를 보고 현재는 스케일링 수동 설정
추후 자동화 고도화 예정

2. 참석 후기

AWS KRUG - 티맵 네트워크 재조립하기 (많은 VPC 효율적으로 관리하기) 에 이어 같은 밋업에서 들은 두번째 세션이었다. 발표 시간은 생각보다 짧았는데, 백엔드 개발자로 고민해볼만한 유즈케이스여서 더 관심있게 듣게 되었다 (사실 이걸 들으러 간거였다.)
개선된 프로세스의 설명을 간단하게 해주셔서 디테일하게 몇가지 여쭙고 싶었는데 (예를 들어, validation 로직이 어떻게 진행되는지? 어떤것까지 validation 했는지, ElastiCache에서는 어떤 값을 저장했는지) , 타이밍을 놓쳐서 물어보질 못했다. 조금더 용기해서 뒷풀이를 갔어야했나.. 아쉬움이 든다.