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. 1.Token Bucket과 Leaky Bucket의 핵심 차이는?
  2. 2.Sliding Window가 Fixed Window보다 정확한 이유는?
  3. 3.분산 Rate Limiting의 어려움은?
  4. 4.Throttling(429)과 Backpressure의 차이는?
  5. 5.API Rate Limit에서 429 응답에 포함해야 할 헤더는?