Chào anh em, nếu bạn đang xây dựng một API public hoặc hệ thống có lượng traffic lớn, chắc chắn bạn không thể bỏ qua Rate Limiting. Không có nó, server của bạn rất dễ bị "bế đi" bởi các cuộc tấn công DDoS, brute-force hoặc những công cụ cào (scrape) dữ liệu vô tội vạ.
Cùng mổ xẻ xem Rate Limiting hoạt động thế nào và làm sao để tích hợp nó một cách chuẩn bài nhé!
🧠 5 Thuật Toán Rate Limiting "Kinh Điển"
Không phải cứ đếm số lượng request là xong. Dưới đây là các thuật toán từ dễ đến khó mà các kỹ sư hệ thống thường dùng:
- Fixed Window Counter: Đếm số request trong một khoảng thời gian cố định (vd: 00:00 - 00:59). Nhược điểm: Rất dễ bị lách luật ở thời điểm giao thoa giữa 2 cửa sổ.
- Sliding Window Log: Lưu lại dấu thời gian (timestamp) của từng request. Chính xác 100% nhưng cực kỳ tốn RAM.
- Sliding Window Counter: Lai giữa 2 cách trên. Vừa đảm bảo tính chính xác vừa tiết kiệm bộ nhớ.
- Token Bucket (Xô Token): Thuật toán phổ biến nhất (Amazon, Stripe đang dùng). Cho phép burst traffic (lưu lượng bùng nổ) trong giới hạn cái xô chứa.
- Leaky Bucket (Xô Rò Rỉ): Request chảy vào xô và rỏ rỉ ra với tốc độ cố định. Giúp traffic luôn ổn định (smooth out traffic).
💻 Thực Hành: Triển Khai Rate Limiting Bằng Python + Redis
Dưới đây là một đoạn code mô phỏng Rate Limiting cơ bản dùng Python và Redis (thuật toán Fixed Window đơn giản):
import redis
import time
r = redis.Redis(host='localhost', port=6379, db=0)
def is_request_allowed(user_id, limit, window_seconds):
key = f"rate_limit:{user_id}"
current_time = int(time.time())
# Bắt đầu một pipeline để thực hiện nhiều lệnh Redis cùng lúc
pipe = r.pipeline()
pipe.incr(key, 1)
pipe.expire(key, window_seconds)
results = pipe.execute()
count = results[0]
if count > limit:
return False
return True
# Ví dụ sử dụng:
user = 'user123'
limit_per_minute = 100
window = 60
if is_request_allowed(user, limit_per_minute, window):
print("✅ Yêu cầu được chấp nhận.")
else:
print("❌ Yêu cầu bị từ chối: Đã vượt quá giới hạn.")
⚠️ Lưu ý cực mạnh: Trong môi trường Production với hàng ngàn request đồng thời, đoạn code trên rất dễ dính Race Condition. Cách giải quyết "chuẩn chỉ" nhất là sử dụng Lua Script chạy thẳng trên Redis để đảm bảo tính nguyên tử (atomic). (Bạn có thể tham khảo thêm cấu trúc logic bị lỗi ở file Ảnh màn hình 2026-05-09 lúc 09.11.54.png để hiểu rõ hơn lý do vì sao khung mã nguồn thường bị vỡ).
🚧 Những Sai Lầm "Sập Hầm" Khi Triển Khai
- Chặn nhầm IP (Dùng chung Wi-Fi/NAT): Đừng chỉ dựa vào IP để block! Rất nhiều user dùng chung một mạng NAT. Hãy kết hợp API Key, User ID (JWT) hoặc Browser Fingerprinting để định danh.
-
Trả về sai HTTP Status Code: Khi user vượt quá giới hạn, bắt buộc phải trả về mã
429 Too Many Requests(chứ đừng trả 500 hay 403). - Làm ảnh hưởng SEO: Googlebot vào cào trang mà bị rate limit chặn thì "toang" luôn thứ hạng! Nhớ đưa dải IP của Googlebot vào Whitelist.
Anh em trong team đang dùng API Gateway (Kong, Nginx) để chặn hay tự viết logic Rate Limiting ở tầng Backend? Cùng chia sẻ kinh nghiệm nhé! 👇
🔥 Khám phá thêm: Nếu anh em quan tâm đến System Design và kiến trúc Backend, hãy ghé thăm blog ITPrep để đọc thêm nhiều bài viết thực chiến cực chất!
Nguồn tham khảo: ITPrep - Rate Limiting: Hướng Dẫn Chuyên Sâu Từ A-Z Cho Lập Trình Viên
Top comments (0)