Redis 데이터 타입 설계
MySQL의 부하 문제를 해결하고 효율적인 데이터 처리를 위해 Redis를 도입하기로 하였다. Redis는 다양한 데이터 타입을 제공하므로 시스템의 요구사항에 맞게 설계가 가능하다. 특히 쿠폰 발급 서비스에서 중요한 동시성 제어, 선착순 조건 처리, 그리고 검증 조건 처리(수량 조회 및 중복 발급 방지)에 적합한 데이터 구조를 선택하여 구현 방안을 모색한다. 이번 내용에서는 Redis의 List, Set, Sroted Set의 특징을 간단히 확인하고 요구사항에 맞는 데이터 구조를 비교한다.
특징
•
순서가 있는 요소들의 집합
•
스택(Last-In-First-Out) 또는 큐(First-In-First-Out) 형태로 구현 가능
•
중복 허용
선착순 조건 처리(쿠폰요청)
•
RPUSH: 리스트의 끝에 요소 추가, 선착순으로 요청을 처리하기 위해 요청을 순차적으로 추가
•
LPOP: 리스트의 앞에서 요소 제거 및 반환, 가장 먼저 추가된 요청이 가장 먼저 처리되어 FIFO를 구현
검증 조건 처리
•
수량 조회: LLEN 명령어로 리스트에 저장된 요청 수 확인
•
중복 발급 검증: 중복을 허용하기 때문에 추가적인 검증이 필요 (LPOS 명령어 사용)
한계
•
중복 방지 처리 과정이 복잡하며, LPOS를 사용한 중복 탐색은 O(n) 시간 복잡도를 가짐
•
선착순 조건은 쉽게 구현 가능하나, 중복 발급 처리에 부적합
List 명령어 예시:
┌────────────────────────────┐
│ Redis List │
│ (Coupon Queue) │
├────────────────────────────┤
│ "UserA_Request" │ ← Front (LPOP)
│ "UserB_Request" │
│ "UserC_Request" │ ← Rear (RPUSH)
└────────────────────────────┘
Actions:
1. RPUSH "UserD_Request" 사용자D 요청으로 RPUSH 추가
┌────────────────────────────┐
│ Redis List │
│ (Coupon Queue) │
├────────────────────────────┤
│ "UserA_Request" │ ← Front (LPOP)
│ "UserB_Request" │
│ "UserC_Request" │
│ "UserD_Request" │ ← Rear (RPUSH)
└────────────────────────────┘
2. LPOP → "UserA_Request" 사용자A
┌────────────────────────────┐
│ Redis List │
│ (Coupon Queue) │
├────────────────────────────┤
│ "UserB_Request" │ ← Front (LPOP)
│ "UserC_Request" │
│ "UserD_Request" │ ← Rear (RPUSH)
└────────────────────────────┘
3. LLEN coupon_queue
결과:3
Java
복사
특징
•
중복 허용하지 않음
•
순서 보장하지 않음
선착순 조건 처리(쿠폰요청)
•
쿠폰요청: SADD로 쿠폰 요청 추가
•
Set의 특성상 순서를 보장하지 않아 선착순 처리 불가능
•
그러나 수량 조회를 통해 선착순 조건을 간접적으로 검증 가능
(예: set 수량, 선착순 쿠폰 수량 비교)
검증 조건 처리
•
수량 조회: SCARD 명령어로 Set의 크기 확인하여 발급 가능 여부 검증
•
중복 발급 검증: SISMEMBER 명령어로 요청 중복 여부 검증 가능
한계
•
순서 보장 불가: 선착순 처리를 직접적으로 할 수 없음
•
요청의 순서를 알 수 없는 한계점있지만 수량조회를 통해서 선착순 발급 가능 여부 검증가능
특징
•
중복 허용하지 않음
•
Score를 활용하여 요소를 정렬 가능
선착순 조건 처리(쿠폰요청)
•
Score를 Timestamp로 사용하여 요청 순서를 정렬 가능
•
명령어:
◦
ZADD: 요청 추가 시 Score(타임스탬프)와 함께 요소 추가
◦
ZRANK: 요청 순서 확인을 위해 요소의 순위 조회
검증 조건 처리
•
수량 조회: ZCARD 명령어로 Sorted Set의 크기 확인
•
중복 발급 검증: ZADD의 반환 값을 통해 중복 여부 확인 가능
한계
•
Timestamp 버그: 동일한 Timestamp의 요청이 발생할 경우 정렬이 신뢰할 수 없음
•
성능 문제: O(log N) 시간 복잡도로 데이터량이 증가할수록 성능 저하
•
관리 어려움: Score를 관리해야 하며, 추가적인 로직이 필요
정리 및 결론
항목 | List | Set | Sorted Set |
특징 | - Stack, Queue 구현 가능<br>- 중복 허용 | - 중복 허용하지 않음
- 순서 보장하지 않음 | - 중복 허용하지 않음
- Score를 사용하여 정렬 가능 |
선착순 조건 처리 | - 유저 요청을 큐에 추가하여 FIFO 방식으로 처리
- RPUSH, LPOP 사용 | - 순서를 보장하지 않아 직접적인 선착순 처리 불가
- 수량 조회로 간접 검증 | - Score를 Timestamp로 활용하여 요청 순서로 정렬
- ZADD, ZRANK 사용 |
검증 조건 처리 | - 수량 조회: LLEN
- 중복 발급 검증: LPOS 필요 | - 수량 조회: SCARD
- 중복 발급 검증: SISMEMBER | - 수량 조회: ZCARD
- 중복 발급 검증: ZADD의 결과 값 사용 |
성능 | - 중복 검증 시 O(n) 탐색 | - 중복 검증 시 O(1) 탐색 | - 중복 검증 시 O(log N) 탐색 |
장점 | - 큐 구현이 간단
- 선착순 처리 용이 | - 중복 방지 간단
- 수량 검증 효율적 | - 선착순 처리 가능
- 중복 방지 간단 |
단점 | - 중복 발급 검증 복잡
- 발급 수량 검증 비효율적 | - 선착순 처리 불가 | - 동일 Timestamp 처리 버그
- Score 관리 복잡
- 데이터 많아지면 O(logN) 성능 안좋아 ? |
추천 활용 | - 단일 서버 환경에서 선착순 요청 처리 | - 대규모 시스템에서 효율적인 중복 방지 및 수량 검증 필요 | - 선착순과 중복 방지가 모두 필요한 경우 |
최적의 선택: Set
이유:
•
간단한 구현: Set은 중복을 허용하지 않아 별도의 중복 검증 로직이 필요없으며, SADD와 SISMEMBER 명령어를 통해 선착순 조건, 검증 조건을 구현한다.
•
고성능: Set은 시간 복잡도로 대규모 트래픽에서도 안정적으로 동작한다.
•
유지보수 용이: Sorted Set 의 Score 관리가 필요없고, 구조가 단순하여 관리가 용이하다.
Set을 활용하면 중복발급을 효과적으로 방지하면서, 수량 조회를 통해 선착순 발급 가능 여부를 간단히 검증할 수 있다. 이러한 특정 덕분에 대규모 트래픽을 처리하는 쿠폰 발급 시스템에 적합한 데이터구조로 판단된다.
Related Posts
Search