sihyeonn commented on code in PR #12756:
URL: https://github.com/apache/apisix/pull/12756#discussion_r2652145297
##########
apisix/plugins/limit-count/limit-count-redis-cluster.lua:
##########
@@ -39,7 +40,56 @@ local script = core.string.compress_script([=[
]=])
-function _M.new(plugin_name, limit, window, conf)
+local script_sliding = core.string.compress_script([=[
+ assert(tonumber(ARGV[3]) >= 1, "cost must be at least 1")
+
+ local now = tonumber(ARGV[1])
+ local window = tonumber(ARGV[2])
+ local limit = tonumber(ARGV[3])
+ local cost = tonumber(ARGV[4])
+ local req_id = ARGV[5]
+
+ local window_start = now - window
+
+ redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, window_start)
+
+ local current = redis.call('ZCARD', KEYS[1])
+
+ if current + cost > limit then
+ local earliest = redis.call('ZRANGE', KEYS[1], 0, 0, 'WITHSCORES')
+ local reset = 0
+ if #earliest == 2 then
+ reset = earliest[2] + window - now
+ if reset < 0 then
+ reset = 0
+ end
+ end
+ return {-1, reset}
+ end
+
+ for i = 1, cost do
+ local member = req_id .. ':' .. i
+ redis.call('ZADD', KEYS[1], now, member)
+ end
Review Comment:
@spacewander @Baoyuantop Thank you so much for the excellent suggestion and
providing both the Cloudflare blog reference and the implementation code! This
was incredibly helpful.
I've implemented both approaches in this PR to give users flexibility based
on their requirements:
**Sliding window goal**
Fixed window allows burst traffic at window boundaries. For example, with
`limit=100, time_window=60s`, a user could make 100 requests at 11:00:59 and
another 100 at 11:01:00 — effectively 200 requests in 2 seconds, defeating the
rate limit purpose.
Sliding window prevents this by enforcing the limit over any rolling time
period.
1. Exact sliding window (`window_type: "sliding"`)
- 100% accuracy using sorted sets
- ~100 bytes per request
- Best for: Payment APIs, security-sensitive endpoints where burst
prevention is critical
2. Approximate sliding window (`window_type: "approximate_sliding"`)
- ~99.997% accuracy (0.003% error, validated with 400B+ requests per
Cloudflare)
- ~16 bytes per key (counter-based: `prev_count × (1 - rate) + curr_count`)
- Best for: High-traffic APIs, CDN edges, cost-sensitive deployments
Test cases have been added for both modes. Please let me know if you'd like
any adjustments!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]