Reputation: 23
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
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