'Redis INCRBY with limits
I'd like to know if there is a way to perform this in redis with a single roundtrip from my app:
For a given key K
, its possible value V
is any of the integers inside the range [A, B]
. Basically, it has an upper and lower boundary.
When an INCRBY
or DECRBY
command is issued (eg. INCRBY key 10
) it will be executed only if the resulting value is not out of bounds.
I need this operation to be atomic, and I wanted to know if there was a way to avoid Lua scripting for this.
Thank you.
Solution 1:[1]
This answer might not be what you expect. But I have to say that Lua scripting is the crystal clear solution.
-- range-incrby.lua key , increment
local key = KEYS[1]
local increment = ARGV[1]
local cnt = redis.call('get', key) or 0
cnt = cnt + increment
if (cnt >= 0 and cnt <= 100) then
redis.call('set', key, cnt)
return cnt
end
Also, if the range is [0, 2^N - 1]
, then you can use BITFIELD
command with overflow control to solve the problem.
BITFIELD key OVERFLOW FAIL INCRBY uN 0 increment
However, that seems not your case.
Solution 2:[2]
I have to agree that the Lua script solution is clear and efficient. In that case, another variation taking the limit and decrement as a argument can be implemented as.
local value=redis.call("get", KEYS[1]) or 0
local decrement=tonumber(ARGV[1])
local limit=tonumber(ARGV[2])
if (value - decrement) < limit then value = redis.call("decrby", KEYS[1], value - limit)
else value = redis.call("decrby", KEYS[1], decrement) end
return value
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 | |
Solution 2 | Filipe Andrade |