Giao diện
Thực hành: Thiết kế Distributed Rate Limiter
🎯 Mục tiêu
🎯 Sau bài thực hành này, bạn sẽ:
- So sánh Token Bucket, Sliding Window, Fixed Window
- Thiết kế rate limiter phân tán với Redis
- Giải quyết consistency trong multi-region deployment
- Xử lý race condition với atomic operations
Yêu cầu hệ thống
Functional: Giới hạn request theo user/IP/API key, multiple rules, HTTP 429, metrics.
Non-functional: Check dưới 1ms (p99), sai số <1%, fail-open khi down, 1M RPM.
So sánh thuật toán
| Thuật toán | Ưu điểm | Nhược điểm | Use case |
|---|---|---|---|
| Fixed Window | Đơn giản | Burst 2x tại biên | Internal API |
| Sliding Window Counter | Cân bằng | Xấp xỉ | General |
| Token Bucket | Cho phép burst hợp lý | Cần tuning | Public API |
| Leaky Bucket | Output ổn định | Không burst | Streaming |
Kiến trúc
Thiết kế chi tiết
Token Bucket với Redis
- Key:
ratelimit:{user_id}:{endpoint}, Fields:tokens,last_refill - Atomic Lua script: Tính refill → update → check → allow/deny trong 1 operation (tránh race condition)
Rules
Per-user (100 req/min free, 1000 premium), per-IP (50/min), per-endpoint (/api/upload 10/min). Most specific wins.
🎯 Scenario Choice
Multi-region Consistency
Deploy 2 region. User limit 100 req/min, gửi 60 đến mỗi region → bypass (120).
Centralized Redis: Consistency hoàn hảo, latency 50-100ms. Local + Async Sync: Latency thấp, eventual consistency. Split Quota: Chia 50/50, không sync nhưng lãng phí.
💡 Production chọn Local + Async Sync. Sai số 5-10% acceptable — rate limiting ngăn abuse, không cần exact.
Trắc nghiệm
🧠 Quiz
Câu 1: Token Bucket phù hợp hơn Fixed Window cho public API vì?
- [ ] A) Ít memory hơn
- [x] B) Cho phép burst hợp lý, Fixed Window cho phép 2x limit tại biên window
- [ ] C) Không cần centralized storage
- [ ] D) Fixed Window không implement được với Redis
💡 Fixed Window reset tại boundary: 100 req cuối phút 1 + 100 đầu phút 2 = 200 trong 2s. Token Bucket smooth hơn.
🧠 Quiz
Câu 2: Rate limiter bị down, xử lý thế nào?
- [ ] A) Block mọi request (fail-closed)
- [x] B) Cho request đi qua, log warning (fail-open) — availability quan trọng hơn
- [ ] C) Dùng cached decision
- [ ] D) Chuyển sang client-side limiting
💡 Rate limiter là safety mechanism. Fail-closed = toàn bộ API block, nghiêm trọng hơn vài request thừa.
🧠 Quiz
Câu 3: Sliding Window Counter ước lượng rate bằng cách nào?
- [ ] A) Lưu timestamp mọi request rồi đếm
- [ ] B) HyperLogLog ước lượng
- [x] C) Kết hợp counter window hiện tại và trước theo tỷ lệ overlap
- [ ] D) Chia sub-window nhỏ cộng tất cả counter
💡 Công thức:
count = current + previous * overlap%. Ở phút 1:30: count_m2 + count_m1 * 0.5.