Throttling: vì sao in-memory rate limit "biến mất" sau khi scale ngang, và chọn token bucket hay sliding window
Throttling là cơ chế giới hạn số request một client (user, IP, API key, tenant) được xử lý trong một khoảng thời gian, để chống abuse, bảo vệ downstream, và phân bổ công bằng dung lượng service. Định nghĩa nghe đơn giản, nhưng lý do dev gặp nó trong việc thật lại rất cụ thể: sau khi scale service từ 1 pod lên 8 pod, cùng cấu hình "100 req/min mỗi user" đột nhiên trở thành 800 req/min thực tế — vì mỗi pod đếm riêng trong RAM, và load balancer rải request đều tám hướng. Rate limit vẫn "chạy", log không có lỗi, nhưng downstream vẫn bị flood. Đó là failure mode dẫn tới việc phải chuyển counter sang store phân tán, và kèm theo là câu hỏi chọn algorithm nào — token bucket, sliding window, hay leaky bucket — mỗi cái đánh đổi khác nhau.
Cơ chế hoạt động
Bốn thuật toán phổ biến, khác nhau ở cách đếm và cách xử lý burst.
Fixed window counter. Chia thời gian thành khung cố định (mỗi phút bắt đầu tại giây 0). Mỗi request INCR một key rl:{user}:{minute}, nếu counter vượt limit thì reject. Đơn giản nhất, một INCR + EXPIRE trên Redis là xong. Nhược điểm cứng: tại biên khung có thể chịu gấp đôi limit trong một cửa sổ trượt — user gửi 100 req vào giây 59 của phút 12:00, rồi 100 req vào giây 01 của phút 12:01, tức 200 req trong 2 giây thật, trong khi limit là 100/phút.






