Phase 5레슨 23
Rate Limiting
Token Bucket, Leaky Bucket, Sliding Window, Distributed Rate Limit — 트래픽 제어
💡ELI5·
토큰과 양동이
Token Bucket: 버킷에 1초마다 100개 토큰 충전 (최대 100개) 요청 1개 = 토큰 1개 소비 버스트: 버킷에 100개 있으면 1초에 100개 한번에 처리 가능 Leaky Bucket: 버킷에 요청이 들어오고, 1초마다 100개씩 새어나감 버킷이 꽉 차면 초과 요청 거부 일정 속도(100/s)만 처리, 버스트 불가
💡 비유 — Token Bucket = 선불 교통카드. 충전해 둔 만큼 한 번에 긁을 수 있다(버스트). Leaky Bucket = 수도꼭지. 일정한 속도로만 물이 나오고, 양동이가 넘치면 더 이상 안 받는다(일정 속도).
🔬Deep Dive·
Rate Limit 알고리즘 비교
| 알고리즘 | 버스트 | 일정 속도 | 메모리 | 적합 |
|---|---|---|---|---|
| Fixed Window | 경계 버스트 가능 | 창 내에서만 | 낮음 (카운터 1개) | 간단한 API |
| Sliding Window Log | 없음 | 보장 | 높음 (타임스탬프 저장) | 정확성 중요 |
| Sliding Window Counter | 제한적 | 근사 보장 | 낮음 (2개 카운터) | 실용적 균형 |
| Token Bucket | 허용 | 평균만 보장 | 낮음 | 버스트 허용 API |
| Leaky Bucket | 불가 | 엄격 보장 | 낮음 | 일정 속도 필요 |
🔬Deep Dive·
분산 Rate Limiting
방법 1: 중앙 저장소 (Redis) Server1 ──→ Redis (공유 카운터) ←── Server2 정확하지만 Redis 지연 + SPOF 방법 2: 로컬 카운터 + 주기적 동기화 Server1: 1000/s 중 500 담당 Server2: 1000/s 중 500 담당 빠르지만 서버 추가/장애 시 부정확 방법 3: Token Server (Google SRE) 전용 토큰 서버가 토큰 발급 클라이언트는 토큰 받아 처리
💻Code·
Token Bucket 구현 (Redis)
-- Redis Lua 스크립트 (원자적 실행)
-- 키: rate:user:123
-- 인자: capacity(100), refill_rate(10/s), now(timestamp)
local key = KEYS[1]
local capacity = tonumber(ARGV[1])
local refill_rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local bucket = redis.call('HMGET', key, 'tokens', 'last_refill')
local tokens = tonumber(bucket[1]) or capacity
local last_refill = tonumber(bucket[2]) or now
-- 토큰 충전
local elapsed = now - last_refill
tokens = math.min(capacity, tokens + elapsed * refill_rate)
if tokens >= 1 then
tokens = tokens - 1
redis.call('HMSET', key, 'tokens', tokens, 'last_refill', now)
redis.call('EXPIRE', key, 60)
return 1 -- 허용
else
redis.call('HMSET', key, 'tokens', tokens, 'last_refill', now)
return 0 -- 거부
end⚖️Trade-off·
Rate Limiting의 Trade-off
| 이점 | 대가 |
|---|---|
| 서버 보호 (과부하 방지) | 사용자 경험 저하 (429) |
| 공평한 자원 분배 | 분산 환경에서 정확성 어려움 |
| DDoS 완화 | 알고리즘 선택 복잡성 |
| API 비즈니스 모델 (사용량 제한) | 클라이언트가 재시도 로직 구현해야 |
❓ 체크포인트 질문
- 1.Token Bucket과 Leaky Bucket의 핵심 차이는?
- 2.Sliding Window가 Fixed Window보다 정확한 이유는?
- 3.분산 Rate Limiting의 어려움은?
- 4.Throttling(429)과 Backpressure의 차이는?
- 5.API Rate Limit에서 429 응답에 포함해야 할 헤더는?