3

Building a sliding window rate limiter with Redis

 1 year ago
source link: https://gist.github.com/itamarhaber/254bac4283d1675c5a5569639b0322aa
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Some thoughts about "Building a sliding window rate limiter with Redis" · GitHub

Instantly share code, notes, and snippets.

Some thoughts about "Building a sliding window rate limiter with Redis"

Reading Building a sliding window rate limiter with Redis, and w/o addressing the actual logic (which may or may not work).

Optimize by:

  1. Lua seems a much better choice: idiompotent, portable, server-side, less bandwidth, atomic...
  2. The call to ZRANGEBYSCORE seems to be unused, should be commented out if so
  3. Looking at the use of ZRANGE, it appears that ZCARD it what's actually needed

The (untested) Lua snippet:

local tok = KEYS[1]
local now, win = tonumber(ARGV[1]), tonumber(ARGV[2])

-- redis.call('ZRANGEBYSCORE', tok, 0, now - win)
local ret = redis.call('ZCARD', tok)
redis.call('ZADD', tok, now, now)
redis.call('EXPIRE', tok, win)

return ret

The (untested) PHP:

// composer require predis/predis
require_once __DIR__ . '/vendor/autoload.php';

$maxCallsPerHour = 5000;
$slidingWindow = 3600;

$now = microtime(true);
$accessToken = md5('access-token');

$client = new Predis\Client();
$result = $client->evalsha('the-sha1-of-the-snippet');

$remaining = max(0, $maxCallsPerHour - count($result));

if ($remaining > 0) {
    echo sprintf('%s: Allowed and %d remaining', $now, $remaining) . PHP_EOL;
} else {
    echo sprintf('%s: Not allowed', $now) . PHP_EOL;
}

This is the lua script we're using atm:

local token = KEYS[1]
local now = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local limit = tonumber(ARGV[3])

local clearBefore = now - window
redis.call('ZREMRANGEBYSCORE', token, 0, clearBefore)

local amount = redis.call('ZCARD', token)
if amount < limit then
    redis.call('ZADD', token, now, now)
end
redis.call('EXPIRE', token, window)

return limit - amount

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK