'Redis increment only if < certain number?
How do I call .incr on a key and have it increment ONLY if the resulting number is < than a certain number without having to call .get beforehand?
The reason why is calling .get beforehand is problematic is because if I have multiple threads. There could possibly be 100 threads that have executed the first line below, they all get the value "0" and as a result, all increment. A race condition, if you will.
currentVal = $redis.get('key') #all threads could be done executing this but not yet the below if condition.
if(currentVal < 3)
$redis.incr('key') #1
end
Solution 1:[1]
You can either use WATCH
/MULTI
/EXEC
semantics for optimistic locking, or compose a Lua such as this one (not tested):
local r=redis.call('GET', KEYS[1])
if r < ARGV[1] then
redis.call('INCR', KEYS[1])
end
Solution 2:[2]
I took the idea for lua script from Itamar Haber, improve it so it works, and added return values to know what happened on client side.
local r=redis.call('GET', KEYS[1])
if not r or tonumber(r) < tonumber(ARGV[1])
then
redis.call('INCR', KEYS[1])
return 1
else
return 0
end
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Itamar Haber |
Solution 2 | Magnielcz |