Context
Table of Content
기존 구조의 문제점
현재 구조
•
사용자 요청 → API 서버 → MySQL 처리(트랜잭션)
과정
1.
N명의 사용자가 API로 요청을 보낸다.
2.
API서버에서는 N개의 요청을 처리한다.
3.
N개의 쿠폰 발급 트랜잭션을 처리 한다.
•
쿠폰조회 (findCouponWithLock(couponId) )
•
쿠폰 발급 검증 및 수량증가(coupon.issue() , issuedQuantity++ )
•
쿠폰 발급 정보 저장 (saveCouponIssue(long couponId, long userId) )
문제점
•
사용자 요청을 직접 DB에서 처리하여 트래픽이 증가할 경우 DB 과부하 발생
•
API서버를 확장(scale-out)해도 트랜잭션 병목은 DB에서 발생하여 성능 한계에 도달
개선 구조: 1단계 - Redis추가
도입배경: MySQL 과부하
•
사용자 요청 → API 서버 → MySQL 처리 구조의 경우, 사용자 요청을 DB에서 직접 처리.
•
쿠폰 이벤트 진행 시 트래픽 증가로 인해 동시성문제와 MySQL 과부하 문제가 발생
변경사항
•
Redis 추가: API 서버와 MySQL 사이에 Redis를 추가하여 사용자 요청 처리 속도 개선.
과정
1.
N명의 사용자가 API로 쿠폰 발급 요청을 보낸다.
2.
쿠폰 요청 처리 서버에서는 쿠폰 발급 대상을 검증하여 사용자에게 {성공, 실패}여부를 응답해주며, Redis에 발급 대상을 전달한다.
3.
쿠폰 발급 성공 대상(couponId, userId)을 Redis에 저장한다.
4.
Redis에 쿠폰 발급 성공 대상을 스케줄링 방식으로 가져와 안정적으로 트랜잭션을 수행한다.
효과
•
MySQL에 직접적으로 부하를 주는 요청을 Redis에서 처리하여 병목 현상 해소
•
Redis를 추가하여 선착순 요청을 빠르게 처리하며 발급 성공한 사용자 정보를 저장한다.
개선구조: 2단계 - 기능 별 서버 분리
도입배경: API 서버의 부하
•
사용자 요청 처리와 트랜잭션을 함께 수행하여 API 서버에서 부하 발생.
변경사항
•
API서버와 발급서버를 분리
•
API서버(coupon-api)는 사용자의 요청 중 발급 성공 대상을 Redis Queue에 저장
•
발급서버(coupon-consumer)는 Redis Queue에서 발급 성공 대상을 DB에 트랜잭션 수행
과정
1.
N명의 사용자가 API로 요청을 보낸다.
2.
coupon-api서버: 사용자 요청 트래픽 처리(사용자요청)
API서버(conpon-api)에서는 N개의 사용자 요청에 대해 발급 검증한다.
•
사용자에게 발급 {성공/실패} 응답
•
검증 성공하면 Redis Queue에 발급성공대상(coupon_id, user_id) 을 저장
3.
coupon-consumer서버: 쿠폰 발급 트랜잭션 처리(MySQL 발급 처리)
쿠폰 발급 처리 서버(coupon-consumer)에서는 스케줄링을 통해 Redis Queue의 발급성공대상(couponId ,userId)을 조회(Pull)하여 MySQL로 트랜잭션 수행 및 발급 처리
효과
•
사용자 요청 트래픽 처리와 쿠폰 발급 트랜잭션을 완전 분리하였다.
◦
Redis : 사용자의 요청 트래픽 처리
◦
MySQL : 쿠폰 발급 트랜잭션 처리
•
Redis Queue로 안정적인 트랜잭션 처리 및 MySQL의 트래픽 부담 감소
•
비동기 구조를 통해서 얻게 되는 이점:
1.사용자에게 즉각적인 응답을 제공하며
2.데이터베이스의 부하를 줄이고 처리 효율성을 높여 병목 현상을 완화 할 수 있다.
Related Posts
Search