1. 서론
1.1. 이벤트 개요
•
상품 주문 이벤트
◦
치킨, 버거, 맥주를 무료로 1만 명에게 제공하는 방식으로 진행
◦
역대 최대 규모
•
장애 상황 대응
◦
선착순 이벤트시 발생하는 장애는 고객과 개발팀 모두에게 불만족스러운 경험을 남기므로 문제를 피하기 위한 방안을 마련 필요
1.2. 목표
•
주요 목표
◦
순간적인 대량 트래픽을 소화하여 선착순 주문 이벤트를 무사히 진행
◦
이벤트가 없는 일반 주문에 영향을 주지 않도록 장애 격리
•
서브 목표
◦
짧은 개발 기간 내에 빠르게 개발하고 쉽게 테스트 진행
◦
기존 시스템을 최대한 건드리지 않기
2. 기존 주문 시스템 파악
2.1. 기존의 주문 시스템
•
고객이 메뉴를 장바구니에 담고 주문을 하면 다양한 밸리데이션을 거쳐 주문 데이터가 처리됨
•
주문이 생성되면 수십 번의 API 호출이 발생하며, 여러 시스템이 연결되어 작동함
2.2. 이벤트 진행 예상 문제점
•
이벤트를 진행하게 되면 예상보다 훨씬 많은 트래픽이 발생할 수 있음
◦
주말 피크 3000 RPM
◦
이벤트 최고 47만 RPM
•
시스템 장애 발생 가능성
◦
평소 최고 트래픽 대비 150배 이상의 순간 트래픽
◦
스케일 아웃 /스케일 업으로 대응에는 한계가 있음
◦
예측 실패로 인해 장애가 발생할 수 있음
3. 이벤트 처리 시스템의 전략과 구현
고객의 주문 처리 시스템을 순서대로 처리하자는 전략을 수립
3.1. 큐 시스템
•
기능
◦
모든 이벤트 대상에게 번호표 발급
◦
대기열
▪
번호표를 발급받은 사용자를 줄을 세움
▪
대기열의 사용자에게 현재 몇번째 대기순서인지 노티
◦
참가열
▪
서버가 소화할 수 있는 만큼만 사용자들 입장
•
고려 사항
◦
고성능 처리 가능 (Redis)
•
Redis
◦
많은 서비스에서 사용하는 검증된 저장소
◦
입/출력이 빠른 인메모리 데이터베이스
◦
다양한 자료구조 지원, 요구사항 쉽게 해결 가능
3.2. 구현
•
설계와 상세 구현
설계 | 구현 SORTED SET | |
Step 1 | 이벤트 주문을 요청한대로 순서대로 처리 | ZADD 데이터 추가 시 부여한 스코어에 따라 정렬 |
Step 2 | 대기중인 사용자에게 현재 대기순번을 제공 | ZRANK 현재 순위 조회 |
Step 3 | 일정한 수 만큼 대기열 → 참가열 이동 | ZRANGE 일정한 수 만큼 리스트 조회 |
•
레디스 고려사항
◦
KEYS 명령어 사용 금지
▪
풀스캔, 시간복잡도 O(n)
▪
싱글 스레드
◦
각 명령어의 시간복잡도 확인
▪
sorted Set의 경우 시간복잡도 O(log(n))
▪
데이터가 많아질 수록 성능 저하
3.3. 큐 시스템 플로우
1.
이벤트 주문 요청
•
프로모션 API → 대기번호 생성 및 대기열 추가
•
대기 번호 발급
2.
참가열 진입까지 대기 (폴링)
3.
프로모션 스케쥴러
•
1초마다 설정된 값 만큼 대기열 → 참가열 이동
4.
기존 주문 플로우 처리
4. 기존 시스템과의 통합
4.1. 주문 라우터 활용
•
주문 시스템으로 요청 들어오는 출입구
•
RULE에 따라 API HOST를 변경할 수 있는 라우팅 서버
•
RULE은 회원번호, 업소번호, 지역코드로 설정
•
WebFlux + Netty 논 블로킹 서버
•
1만 TPS도 거뜬히 처리 가능
4.2. RULE을 활용하여 라우팅 진행
•
RULE에 회원번호, 업소 번호가 있는 경우 → 이벤트 API로 라우팅
•
RULE에 회원번호, 업소 번호가 없는 경우 → 기존 API로 라우팅
4.3. 쿠폰 시스템 추가 고도화
•
기존 쿠폰 시스템에 큐 추가
•
쿠폰이 발급될 때마다 회원번호를 큐에 저장
•
주문 이벤트 처리기
◦
큐에 저장된 회원번호를 주문라우터 RULE에 추가
•
해당 회원번호는 이벤트 API로 라우팅 가능해짐
•
최종 주문 라우터 플로우
5. 최종 아키텍처
•
이벤트에 영향없이 일반 주문은 가능하도록 장애 격리
6. 이벤트 모니터링
•
CloudWatch
◦
주요 서버 지표와 대시보드 구성
•
프로모션 어드민 페이지
◦
이벤트 진행중 부하 상황 지속적으로 체크
◦
대기열, 참가열 모니터링
◦
변수 셋팅
▪
프레셔 값, 즉 처리되는 요청의 수치를 통해 서버의 부하를 조절하는 데 사용