Jim
Jim

Reputation: 23

What is the race condition for Redis INCR Rate Limiter 2?

I have read the INCR documentation here but I could not understand why the Rate limiter 2 has a race condition.

In addition, what does it mean by the key will be leaked until we'll see the same IP address again in the documentation?

Can anyone help explain? Thank you very much!

Upvotes: 2

Views: 1730

Answers (1)

for_stack
for_stack

Reputation: 22886

You are talking about the following code, which has two problems in multiple-threaded environment.

1. FUNCTION LIMIT_API_CALL(ip):
2. current = GET(ip)
3. IF current != NULL AND current > 10 THEN
4.     ERROR "too many requests per second"
5. ELSE
6.     value = INCR(ip)
7.     IF value == 1 THEN
8.         EXPIRE(ip,1)
9.     END
10.    PERFORM_API_CALL()
11.END

the key will be leaked until we'll see the same IP address again

If the client dies, e.g. client is killed or machine is down, before executing LINE 8. Then the key ip won't be set an expiration. If we'll never see this ip again, this key will always persist in Redis database, and is leaked.

Rate limiter 2 has a race condition

Suppose key ip doesn't exist in the database. If there are more than 10 clients, say, 20 clients, execute LINE 2 simultaneously. All of them will get a NULL current, and they all will go into the ELSE clause. Finally all these clients will execute LINE 10, and the API will be called more than 10 times.

This solution fails, because these's a time window between LINE 2 and LINE 3.

A Correct Solution

value = INCR(ip)
IF value == 1 THEN
    EXPIRE(ip, 1)
END
IF value <= 10 THEN
    return true
ELSE
    return false
END

Wrap the above code into a Lua script to ensure it runs atomically. If this script returns true, perform the API call. Otherwise, do nothing.

Upvotes: 5

Related Questions