I use INCR and EXPIRE to implement rate limiting, e.g., 5 requests per minute:
if EXISTS counter
count = INCR counter
else
EXPIRE counter 60
count = INCR counter
if count > 5
print "Exceeded the limit"
However, 5 requests can be sent at the last second minute one and 5 more requests at the first second of minute two, i.e., 10 requests in two seconds.
How can this problem be avoided?
Update: I came up with this list implementation. Is this a good way to do it?
times = LLEN counter
if times < 5
LPUSH counter now()
else
time = LINDEX counter -1
if now() - time < 60
print "Exceeded the limit"
else
LPUSH counter now()
LTRIM counter 5
You could switch from “5 requests in the last minute” to “5 requests in minute x”. By this it would be possible to do:
If you want to keep using “5 requests in the last minute”, then you could do
If you have production constraints (especially performance), it is not advised to use the
KEYSkeyword. We could use sets instead:This is all pseudo Ruby code, but should give you the idea.