Redis 기반 쿠폰 발급 서버 설계

최명진·2024년 6월 18일
0

쿠폰 발급 api는 기본으로 RDBMS인 MYSQL을 사용하여 DB에 데이터를 저장하는데 RDBMS에 트래픽이 몰려서 부하를 받을때 성능이 저하되는데, 이를 개선하기 위해서 redis를 사용해보도록 하겠다.

현재 서버 구조는 위와 같이 user가 api 서버로 요청을 보내고, 요청을 처리하는 과정에서 DB에 트랜잭션을 처리한다.
하지만 단순하게 1:1로 트래픽을 요청하지 않고, 사용자는 언제든지 동시에 N명의 유저가 요청을 보낼 수 있다. 그래서 아래 그림처럼 트래픽이 처리 될 것이다.

N명의 유저가 증가하면 이 데이터베이스는 트랜잭션을 감당하지 못할 것이다. 이것을 개선하기 위해
아래와 같은 구조로 서버를 개선시켜본다.

하지만 위의 구조에서 API 서버 또한 유저의 트래픽이 많아지면 불안전한 서버이므로 쿠폰 발급 처리를 API 서버가 아닌 다른 곳에서 해도 되지 않을까? 라는 생각을 하게되었다.


사용자의 요청을 API 서버가 받고, 이 요청을 Redis에서 처리한 후 큐에 발급 대상을 저장하고,
쿠폰 발급 처리 서버에서는 Queue를 조회하여 발급을 처리한다!
하지만 이 요청은 유저가 요청하는 API는 쿠폰 트랜잭션과 분리되어 있어서 쿠폰 발급에 대한 결과를 보장할 수 없기 때문에 이 결과는 동기적이 아닌 비동기적으로 실행된다.
쿠폰 사용의 경우는 비동기로 실행되게 하면 쿠폰이 중복적으로 사용되는 경우가 있어 동기적으로 하는게 좋지만 쿠폰 발급의 경우는 반드시 동기적으로 이뤄져야하는지에 대해서는 정책적으로 5분 이내에 발급됩니다. 등 해결할 방법이 있기 때문에 비동기 방법을 선택해보는 것도 고민해볼 수 있다.

그렇기 때문에, 비동기 쿠폰 발급 시스템을 통해 발급 요청과 과정을 분리하고 발급 요청 서버와 발급 수행 서버를 분리하여 트래픽을 제어해보도록 하겠다.




먼저 앞서 공부한 Redis 자료 구조중 적절하다고 판단된 것은 Sorted Set과 Set이다.
Sorted Set의 경우 timestamp를 score로 비교하면 선착순을 비교할 수 있을 것으로 생각된다. Set의 경우 순서가 보장이 되지 않지만, 어차피 1~100등 모두 선착순으로 같은 쿠폰을 발급 받을 것이므로 수량이 100일때까지를 발급 가능하게 여부를 검증하게 하면 되지 않을까? 라는 생각이 들 기에 선택했다. 쿠폰 발급 Queue의 경우 보통 Kafka와 같은 메시지 큐를 사용하지만, 강의 여건상 Redis의 List로 Queue를 구현하게 되었다.
Sorted Set은 score가 같은 값이면 시간에 따라 정렬되는게 아니라 사전 순으로 정렬되고 각각 언제 요청이 왔는지 등 알 방법이 없다. 또한 데이터가 커질 수록 ZADD의 경우 시간 복잡도가 SET에 비해 느리므로 이점이 크게 없다. 이러한 이유로 Set을 이용하여 쿠폰 발급에 대한 로직을 작성하겠다.

profile
주니어 백엔드 개발자 Choi입니다.

0개의 댓글