@@ -6,12 +6,27 @@ description: |
66 and rate limiting. It includes realistic key sizes and command mixes representative
77 of production traffic (e.g., 400–600B session hashes, ZSETs for analytics, and SETs for tracking).
88
9- Rate limiting is modeled using Redis counters with expiration and readback: each user has a
10- dedicated rate-limit key in the form of `ratelimit:user-<id>:/api/resource`, which is:
11- - incremented (`INCR`) to track API usage,
12- - assigned a TTL (`EXPIRE`) to define the 60-second rate window,
13- - and read (`GET`) to simulate application-side decision-making (e.g., to check if a user is over quota).
14- This models realistic per-user rate-limiting behavior for a single endpoint.
9+ Rate limiting is modeled using an atomic Lua script, inspired by the Upstash Redis example:
10+ https://github.com/upstash/examples/tree/main/examples/ratelimit-with-redis
11+
12+ Each user has a dedicated key in the form of `ratelimit:user-<id>:/api/resource`, which is
13+ used to track usage under a fixed window. The logic is evaluated atomically with the following script:
14+
15+ local key = KEYS[1]
16+ local limit = 100
17+ local window = 60
18+ local current = redis.call("INCR", key)
19+ if current == 1 then
20+ redis.call("EXPIRE", key, window)
21+ end
22+ if current > limit then
23+ return 0
24+ else
25+ return 1
26+ end
27+
28+ This ensures that rate enforcement and usage tracking are done without race conditions, and
29+ mirrors a real-world API quota model.
1530
1631 The workload emphasizes read-heavy patterns to reflect common SaaS access behavior. The overall
1732 **read:write ratio is approximately 85:15**, with read operations covering session access, user-session
@@ -22,7 +37,7 @@ description: |
2237 - Session CRUD (HGETALL, HSET): ~55%
2338 - User session tracking (SMEMBERS, SADD): ~21%
2439 - Organization analytics (ZRANGE, ZADD): ~12%
25- - Rate limiting (INCR, EXPIRE, GET ): ~12%
40+ - Rate limiting (EVAL-based quota check ): ~12%
2641
2742exporter :
2843 redistimeseries :
@@ -37,9 +52,7 @@ exporter:
3752 - $."BEST RUN RESULTS".Sadds."Ops/sec"
3853 - $."BEST RUN RESULTS".Zranges."Ops/sec"
3954 - $."BEST RUN RESULTS".Zadds."Ops/sec"
40- - $."BEST RUN RESULTS".Incrs."Ops/sec"
41- - $."BEST RUN RESULTS".Gets."Ops/sec"
42- - $."BEST RUN RESULTS".Expires."Ops/sec"
55+ - $."BEST RUN RESULTS".Evals."Ops/sec"
4356 - $."BEST RUN RESULTS".Totals."Ops/sec"
4457 - $."BEST RUN RESULTS".Totals."Latency"
4558 - $."BEST RUN RESULTS".Totals."Misses/sec"
@@ -51,9 +64,7 @@ exporter:
5164 - $."ALL STATS".Sadds."Ops/sec"
5265 - $."ALL STATS".Zranges."Ops/sec"
5366 - $."ALL STATS".Zadds."Ops/sec"
54- - $."ALL STATS".Incrs."Ops/sec"
55- - $."ALL STATS".Gets."Ops/sec"
56- - $."ALL STATS".Expires."Ops/sec"
67+ - $."ALL STATS".Evals."Ops/sec"
5768 - $."ALL STATS".Totals."Ops/sec"
5869 - $."ALL STATS".Totals."Latency"
5970 - $."ALL STATS".Totals."Misses/sec"
@@ -63,9 +74,7 @@ exporter:
6374 - $."ALL STATS".Sadds."Percentile Latencies"."p50.00"
6475 - $."ALL STATS".Zranges."Percentile Latencies"."p50.00"
6576 - $."ALL STATS".Zadds."Percentile Latencies"."p50.00"
66- - $."ALL STATS".Incrs."Percentile Latencies"."p50.00"
67- - $."ALL STATS".Gets."Percentile Latencies"."p50.00"
68- - $."ALL STATS".Expires."Percentile Latencies"."p50.00"
77+ - $."ALL STATS".Evals."Percentile Latencies"."p50.00"
6978 - $."ALL STATS".Totals."Percentile Latencies"."p50.00"
7079 - $."ALL STATS".Totals."Percentile Latencies"."p99.00"
7180
@@ -182,15 +191,9 @@ clientconfig:
182191 --command="ZADD org:__key__:sessions 1 user-__key__:session-__key__"
183192 --command-key-pattern=R
184193 --command-ratio=2
185- --command="INCR ratelimit:user-__key__:/api/resource"
186- --command-key-pattern=R
187- --command-ratio=4
188- --command="EXPIRE ratelimit:user-__key__:/api/resource 60"
189- --command-key-pattern=R
190- --command-ratio=1
191- --command="GET ratelimit:user-__key__:/api/resource"
194+ --command='EVAL "local key=KEYS[1];local limit=10;local window=60;local current=redis.call(\"INCR\",key);if current==1 then redis.call(\"EXPIRE\",key,window) end;if current>limit then return 0 else return 1 end" 1 ratelimit:user-__key__:/api/resource'
192195 --command-key-pattern=R
193- --command-ratio=7
196+ --command-ratio=12
194197 --hide-histogram
195198 resources :
196199 requests :
0 commit comments