@@ -6,12 +6,27 @@ description: |
6
6
and rate limiting. It includes realistic key sizes and command mixes representative
7
7
of production traffic (e.g., 400–600B session hashes, ZSETs for analytics, and SETs for tracking).
8
8
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.
15
30
16
31
The workload emphasizes read-heavy patterns to reflect common SaaS access behavior. The overall
17
32
**read:write ratio is approximately 85:15**, with read operations covering session access, user-session
@@ -22,7 +37,7 @@ description: |
22
37
- Session CRUD (HGETALL, HSET): ~55%
23
38
- User session tracking (SMEMBERS, SADD): ~21%
24
39
- Organization analytics (ZRANGE, ZADD): ~12%
25
- - Rate limiting (INCR, EXPIRE, GET ): ~12%
40
+ - Rate limiting (EVAL-based quota check ): ~12%
26
41
27
42
exporter :
28
43
redistimeseries :
@@ -37,9 +52,7 @@ exporter:
37
52
- $."BEST RUN RESULTS".Sadds."Ops/sec"
38
53
- $."BEST RUN RESULTS".Zranges."Ops/sec"
39
54
- $."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"
43
56
- $."BEST RUN RESULTS".Totals."Ops/sec"
44
57
- $."BEST RUN RESULTS".Totals."Latency"
45
58
- $."BEST RUN RESULTS".Totals."Misses/sec"
@@ -51,9 +64,7 @@ exporter:
51
64
- $."ALL STATS".Sadds."Ops/sec"
52
65
- $."ALL STATS".Zranges."Ops/sec"
53
66
- $."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"
57
68
- $."ALL STATS".Totals."Ops/sec"
58
69
- $."ALL STATS".Totals."Latency"
59
70
- $."ALL STATS".Totals."Misses/sec"
@@ -63,9 +74,7 @@ exporter:
63
74
- $."ALL STATS".Sadds."Percentile Latencies"."p50.00"
64
75
- $."ALL STATS".Zranges."Percentile Latencies"."p50.00"
65
76
- $."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"
69
78
- $."ALL STATS".Totals."Percentile Latencies"."p50.00"
70
79
- $."ALL STATS".Totals."Percentile Latencies"."p99.00"
71
80
@@ -182,15 +191,9 @@ clientconfig:
182
191
--command="ZADD org:__key__:sessions 1 user-__key__:session-__key__"
183
192
--command-key-pattern=R
184
193
--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'
192
195
--command-key-pattern=R
193
- --command-ratio=7
196
+ --command-ratio=12
194
197
--hide-histogram
195
198
resources :
196
199
requests :
0 commit comments