U
U
user_of_toster2021-01-16 08:05:43
Redis
user_of_toster, 2021-01-16 08:05:43

How to implement rate-limiting on redis?

Let's say I want to make a limit of 100 requests per day by ip. There are two options to implement rate-limiting. After each request:
1) easy-way : store the key by IP, do incr(), setExpire(currentTime + 1 day);
Pros: easy to implement, don't suffer from performance
Cons: window of 1 day is smeared for several days
2) hard-way : I store all visits, do setExpire for each one individually, count the number of visits using key *. The result is an exact window (1 day).
Pros: hard to implement, performance suffers (?)
Cons: exact window of 1 day, user will be able to make 101 requests after 1 request expires.

Question - 1) how to implement the second option in radish? In my head, there is an option to generate a key like IP:RANDOM_UUID and set expire in 1 day. Then look for the key by IP mask
2) How popular is the second option? Is it possible to put the first and not bathe?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Sokolov, 2021-01-16
@user_of_toster

You can store a list of request times, the IP key.

"192.168.15.20": [11, 22, 33, 44],
"192.168.15.22": [10, 24, 35, 42, 46],

Watch its length (< 100 ?), compare the current time with the last one in the list.
Insert the time of the resolved request at the beginning.
A new request arrives. Further pseudocode:
const ip = request.ip;
const ts = Date.now();
const len = Redis.LLEN(ip);

if (len < 100) { // можно 
  Redis.LPUSH(ip, ts);
  return true; // можно выполнять запрос
}

const last_ts = Redis.LRANGE(ip, -1, -1);

if ((ts - last_ts) < 864e5) { // меньше суток
  return false; 
} else {
  Redis.LPUSH(ip, ts);
  Redis.LTRIM(ip, 0, 99);
  return true;
}

And it's probably worth wrapping it all in MULTI .. EXEC, so that parallel requests from one IP to make a mess.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question