Understanding Rate Limiting: Concepts, Architectures, Algorithms, and a Redis‑Lua Token Bucket Implementation
This article explains what rate limiting is, why it is needed, the typical actions taken when limits are reached, compares single‑node and distributed architectures, reviews four classic limiting algorithms, and provides a practical Redis‑Lua token‑bucket implementation with code examples.
What is rate limiting? Rate limiting restricts the number of requests or transactions a system can handle within a given time window to protect stability and prevent resource exhaustion.
Why use rate limiting? It mitigates sudden traffic spikes, malicious attacks, and helps enforce usage‑based billing by controlling request volume.
Typical rate‑limit actions include rejecting excess requests, degrading service, granting privileged access, delaying processing via queues, and auto‑scaling resources.
Architectures
1. Single‑node rate limiting – applied on a single service instance; protects that node and its downstream services.
2. Distributed rate limiting – coordinates limits across a cluster, ensuring the whole system respects a global quota.
Algorithms
1. Fixed window counter – simple but can allow double the limit during window boundaries.
2. Sliding window counter – records timestamps of each request for more accurate limiting at the cost of higher memory usage.
3. Leaky bucket – smooths request flow by processing at a constant rate; cannot handle bursty traffic within the limit.
4. Token bucket – allows bursts while enforcing an average rate; widely used in practice.
Token bucket implementation with Redis + Lua
The implementation stores limiter state in a Redis hash (fields: last_time, curr_permits, bucket_cap, rate, period) and uses a Lua script to perform atomic updates.
local key = KEYS[1] -- limiter key, e.g., URI
local consume_permits = tonumber(ARGV[1]) -- permits needed per request
local curr_time = tonumber(ARGV[2]) -- current timestamp (ms)
local limiter_info = redis.pcall("HMGET", key, "last_time", "curr_permits", "bucket_cap", "rate", "period")
if not limiter_info[3] then
return -1
end
local last_time = tonumber(limiter_info[1]) or 0
local curr_permits = tonumber(limiter_info[2]) or 0
local bucket_cap = tonumber(limiter_info[3]) or 0
local rate = tonumber(limiter_info[4]) or 0
local period = tonumber(limiter_info[5]) or 0
local total_permits = bucket_cap
local is_update_time = true
if last_time > 0 then
local new_permits = math.floor((curr_time - last_time) / 1000 * rate)
if new_permits <= 0 then
new_permits = 0
is_update_time = false
end
total_permits = new_permits + curr_permits
if total_permits > bucket_cap then
total_permits = bucket_cap
end
else
last_time = curr_time + period * 1000
end
local res = 1
if total_permits >= consume_permits then
total_permits = total_permits - consume_permits
else
res = 0
end
if is_update_time then
redis.pcall("HMSET", key, "curr_permits", total_permits, "last_time", curr_time)
else
redis.pcall("HSET", key, "curr_permits", total_permits)
end
return resTypical usage:
1. Load the script with SCRIPT LOAD to obtain a SHA1.
2. For each request, call EVALSHA {sha1} 1 {uri} 1 {timestamp}.
- Return 1: request allowed.
- Return 0: request rejected (limit exceeded).
- Return -1: no limiter configured for the key.
Conclusion The article covered four rate‑limiting algorithms, highlighted their trade‑offs, and demonstrated a production‑ready token‑bucket solution using Redis and Lua, which offers atomicity, low latency, and easy reuse across services.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
360 Smart Cloud
Official service account of 360 Smart Cloud, dedicated to building a high-quality, secure, highly available, convenient, and stable one‑stop cloud service platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
