주말피크는 3천 RPM이 들어오고 이벤트 최고때는 47만 RPM이 들어옴(기존대비 150배)
AWS를 사용하고 있으니 스케일업, 스케일아웃으로 대응할 수 있지 않을까?
10배를 예상하고 준비를 해도 150배가 들어오면 장애가 발생
결제를 위해서는 PG사가 존재함 ( PG사에서 장애가 발생할 수도 있음)
해결방안
처리할 수 있는 만큼만 순서대로 입장시키자
큐 시스템
모든 이벤트 대상에게 번호표 발급
번포효를 발급받은 사용자를 줄 세우기(대기열)
대기열의 사용자에게 현재 몇번째 대기순서를 알려줌
서버가 소화할 수 있을 만큼 사용자를 입장(참가열)
고성능 처리 가능을 위해 Redis를 선택하여 처리
Why Redis?
많은 서비스에 사용된 검증된 저장소
입/출력이 빠른 In-Memory DB
다양한 자료구조를 지원했기 때문에 다양한 요구사항 처리 가능
대기열 ( Redis의 Sorted Set 사용)
이벤트 주문을 요청한 순서대로 처리 (ZADD - 데이터 추가시 부여한 스코어에 따라 정렬)
대기중인 사용자에게 현재 대기순번을 제공(ZRANK - 현재 순위 조회)
일정한 수만큼 대기열에서 참가열로 이동시키기 ( ZRANGE - 일정한 수만큼 리스트 조회)
Redis 사용시 고려사항
각 명령어의 시간복잡도를 확인
잘 알려진 내용이지만 풀스캔을 하는 O(N) KEYS 명령어 사용 금지 - Redis는 싱글 스레드
Sorted Set : O(log(n))
큐 시스템 플로우
이벤트 주문 요청 -> 대기번호 생성 및 대기열 추가 -> (1초마다 설정된 값 만큼 대기열 -> 참가열으로 이동시킴) -> 참여자들은 이때 참가열진입까지 대기 -> 기존 주문 플로우
이제는 10배의 트래픽이던 100배의 트레픽이 들어오던 큐 시스템을 활용하여 설정한 만큼 일정한 트래픽을 보낼 수 있게 되었습니다.
큐 시스템을 만들긴 했는데 중간에 어떻게 끼워넣을까?
기존에 주문 라우터가 존재했습니다. (주문 라우터의 역할)
주문 시스템으로 요청이 들어오는 출입구
RULE에 따라 API HOST를 변경할 수 있음
RULE은 회원번호, 업소번호, 지역코드로 설정됨
WebFulx + Netty로 이루어진 논블로킹 서버
10000 TPS 거뜬히 처리가능
주문 라우터가 요구사항을 충족했기 때문에 이를 활용하여 큐 시스템을 넣었습니다.기존의 주문 라우터는 요청에 들어있는 회원번호와 업소번호를 가지고 Rule을 확인합니다.그리고 Rule에 설정된 HOST로 라우팅해줍니다.만약 Rule에 없는 요청이 오면 기존서버를 타게됩니다.https://www.youtube.com/watch?v=MTSn93rNPPE여기에 개발을 추가하여 해결하였습니다.쿠폰 시스템에 큐를 붙이고 쿠폰이 발행될때마다 회원번호들을 Rule에 있는 회원LIST에 쭉 넣어줍니다.업소LIST는 요일별로 업소목록을 미리 받아서 할당해 둡니다.https://www.youtube.com/watch?v=MTSn93rNPPE
이제 일반 사용하는 주문 프로세스를 그대로 가게되고 쿠본발급을받고 이벤트업소는 큐 시스템을 타고 가게 됩니다.
https://www.youtube.com/watch?v=MTSn93rNPPE
AWS를 사용하고 있기 때문에 주문 시스템을 복제해서 이벤트용 주문 시스템을 큐 시스템에 붙여놨습니다.
https://www.youtube.com/watch?v=MTSn93rNPPE
이제 드디어 이벤트용 주문에서 장애가 발생하더라도!
일반 사용자는 영향을 받지 않습니다.
https://www.youtube.com/watch?v=MTSn93rNPPE
이제 큐 시스템을 이용하여 2가지 목표를 모두 해결하였습니다.
순간적인 대량 트래픽을 소화하자
이벤트에 영향없이 일반주문은 가능하도록 장애를 격리하자
이벤트 모니터링
CloudWatch 대시보드를 적극 활용하여 주요 서버/지표들을 모니터링프로모션 어드민을 만들어 대기열/참가열을 모니터링하고 각종 변수를 셋팅하면서 대응
부하에 따라서 수치를 조절하면서 이벤트를 진행(대기열에서 몇개를 꺼내서 참가열로 넣을지)
후기
선착순 이벤트는 순간적으로 몰리는 TPS를 감당하기 어렵기 때문에 서버 개발자에게 매우 힘든 이벤트입니다.