Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020
1. PRESENTED BY
Protecting Your API with Redis
Jane Paek – Jane@redislabs.com
Solution Architect Manager, Redis Labs
2. PRESENTED BY
Metering and Rate limiting Uses and Design Elements
Protect and Scale Your Application with Rate Limiting and Metering
1
2
3
Why Redis for Rate Limiting and Metering
Rate Limiting Patterns/ Anti Patterns / Design Considerations
Rate Limiting Demo4
5 Resources
Rate Limiting Webinar January 16th 2020, 9am PST
Redis University FREE classes starting January 21, 2020
3. PRESENTED BY
Metering … It’s Everywhere...
Pay As You Go Freemium Tiered Pricing
Rate LimitingSecurityTraffic Shaping
4. PRESENTED BY
Rate Limiting Casualties
Load Balancer
Bad Actors?
Unanticipated Use Cases?
Programmatic Errors?
5. PRESENTED BY
What Do You Need to Meter and Rate Limit?
Load Balancer
1. who - Method for
determining client
■ API key
■ JWT Token
■ IP address
2. how - Pattern to
measure and limit
resources
3. where - Fast
centralized data store
who how where
6. PRESENTED BY
Why Redis for Metering and Rate Limiting?
In-Database
Analytics
Fast Data
Ingest
High-Speed
Transactions
1. Scales to handle burst access at millions of ops/sec at
sub ms latency
2. Fast centralized store for resource limit and state
3. Optimized commands to control resources
○ Incr/Decr, Count
4. Granular control of resource lifetime
5. “In database” analytics for leaderboards, ranking,
scoring
6. Flexible data structures to meet various metering
designs
Centralized
Store
7. PRESENTED BY
Redis Data Structures for Metering and Rate Limiting
Lists
[ A → B → C → D → E ]
Hashes
{ A: “foo”, B: “bar”, C: “baz” }
Bitmaps
0011010101100111001010
Strings
"I'm a Plain Text String!”
Bit field
{23334}{112345569}{766538}
Key
Streams
🡪{id1=time1.seq1(A:“xyz”, B:“cdf”),
d2=time2.seq2(D:“abc”, )}🡪
Hyperloglog
00110101 11001110
Sorted Sets
{ A: 0.1, B: 0.3, C: 100 }
Sets
{ A , B , C , D , E }
Geospatial Indexes
{ A: (51.5, 0.12), B: (32.1, 34.7) }
8. PRESENTED BY
Counting (How Many)
Redis Commands Used for Metering and Rate Limiting
8
Lists | LLEN key
Set | SCARD key
Sorted Set | ZCARD key
Hash | HLEN key
Hyperloglog | PFCOUNT key
Bitmap |
BITCOUNT key [start end]
EXPIRE key seconds
EXPIREAT key timestamp
PEXPIRE key milliseconds
PEXPIREAT key timestamp
SET key value [EX seconds] [PX milliseconds]
INCR key
INCRBY key increment
HINCRBY key field increment
ZINCRBY key increment member
DECR key
DECRBY key decrement
TTL key
PTTL key
Set Key Expiry
Check Time to Live
Incr/Decr Keys
9. PRESENTED BY
• A rate limiter is a tool that monitors user requests in a defined time
window
• “Users” can be humans or services
• Many different designs, each with tradeoffs in:
– complexity
– data usage
– granularity
• No one size fits all!
• Consider over-limit behavior
Today we are examining Rate Limiters as used in distributed systems
where a central database (Redis!) is needed.
Rate Limiting Design Considerations
9
10. PRESENTED BY
Simple Fixed Window Counter Using String
• Defined number of requests per time interval
• single STRING per client: user:<identifier>:<window start time>
• E.g. user:ip-address:start-timestamp
user:127.0.0.1:1573767000
• Redis commands used: SET(EX), INCR, TTL
• Redis in the background, will expire old keys
14. PRESENTED BY
Fixed Window Example: 5 req/min
* Issue: Between 1:30 to 2:15 we allowed 7 requests within a 1 min window
15. PRESENTED BY
Sliding Window e.g Max 10 req/minute
15
Previous Minute
Sliding 60 sec window
Current Minute
Rejected
requests
16. PRESENTED BY
Sliding Window e.g Max 10 req/minute
16
Previous Minute
Sliding 60 sec window
Current Minute
Trimmed
requests
17. PRESENTED BY
Sliding Window e.g Max 10 req/minute
17
Previous Minute
Sliding 60 sec window
Current Minute
Trimmed
requests
18. PRESENTED BY
Sliding Window Using Sorted Set
18
• Stores timestamps of all requests in one
Sorted Set per user
• Upon new request:
– Add new request timestamp to user’s ZSET
– e.g. ZADD user_1 15000000 15000000
– ZREMRANGEBYSCORE to remove expired timestamps for window
– ZCARD therefore gives number of requests in current window - if larger than limit
deny request
• Sliding Window is extremely accurate, but can be memory expensive
• Consider trimming sorted set when adding and reading the sorted if split
role
• Make sure to expire and extend the expiry of the key when values are
added
Example Redis Sorted Set:
Key Value(timestamp) Score(timestamp)
user_1 : {1500000000 -> 1500000000,
1510000000 -> 1510000000,
....
1576525629 -> 1576525629}
19. PRESENTED BY
Token Bucket Using Hash
• For each unique user, store in a hash:
– Last request’s timestamp
– Count of available “tokens”
• Upon new request:
– Fetch hash (HGETALL)
– Refill tokens based on refill rate using last timestamp as reference (HSET)
– Update hash with current timestamp and decrement token count (HMSET)
– If no tokens left, deny request
• Challenges:
– Redis operations not atomic (can lead to race conditions in distributed environment)
– Consider using Lua or perform optimistic locking using Watch with Multi-Exec for Check
and Set (CAS) operations
19
Example Redis Hash:
Key TimeStamp AvailTokens
user_1 ->{ts:1576523628, tokens:10}
20. PRESENTED BY
Rate Limiting Design Anti-Patterns
• Race conditions
– Naive designs may not scale in distributed systems
– e.g. Token Bucket - look for “get, then set” behaviors
• Rate limiting on a super fast API
– Use 10% of total request time for limiting as a rule of thumb
• Unclear user identification
• Granularity vs Resource consumption vs Complexity
• Keeping things local vs distributed
• Using a slow database
– Traditional disk-based databases unable to cope with throughput demands
at scale
20