Redis Rate Limit Store
The redis.RateLimitStore implements the invoker.RateLimitStore interface using a Lua-based token bucket algorithm for atomic, distributed rate limiting.
Setup
import (
"github.com/redis/go-redis/v9"
eventredis "github.com/isaquesb/go-event-bus/redis"
)
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
store := eventredis.NewRedisRateLimitStore(rdb)
Use with the rate limiter invoker:
invoker.NewRateLimiter(store, invoker.RateLimitConfig{
Rate: 100,
Period: time.Hour,
Burst: 10,
KeyPrefix: "orders:limit:",
}, metrics)
Token Bucket Algorithm
The store uses a Lua script for atomic check-and-decrement:
- Get current tokens and last timestamp from Redis hash
- Calculate token refill based on elapsed time:
refill = (elapsed * rate) / period - Cap tokens at burst limit
- If tokens >= 1: decrement and allow
- If tokens < 1: reject
Redis Key Structure
Keys are Redis hashes with two fields:
| Field | Description |
|---|---|
tokens |
Current available tokens |
ts |
Last update timestamp (milliseconds) |
Keys expire after the configured period.
Example Flow
Configuration: rate=100, period=1h, burst=10
Request 1: tokens=10 → allowed, tokens=9
Request 2: tokens=9 → allowed, tokens=8
...
Request 11: tokens=0 → REJECTED
(time passes, tokens refill)
Request 12: tokens=2.7 → allowed, tokens=1.7
Atomicity
The entire check-refill-decrement operation runs as a single Lua script, ensuring atomicity even under high concurrency across multiple pods.