I'm very very new to redis and still playing around with it. I want to test to see if its relevant to my project but I'm not sure about a specific command I'm running. The users on SO have got me convinced of the performance benefits of using pipelines and transactions so I thought I'd ask how to do this.
Basically I have two statements that I just want to issue and not have to wait for the result(seems like a good candidate for pipe lining. It looks like this:
Does valueX exist?
If it does insert valueY
Its pretty simple but so far all the ways I have been looking into it seem to wait for a response for if ValueX exists, and because I'm doing over a billion loops of my program it grinds it to a halt.
Is this possible? If it helps I'm using Java but haven't settled on which client library(jedis or jredis, still testing). I'm actually not even fully settled on redis but leaning very heavily towards it(seems good for what I'm doing speed wise), so any suggestions are acceptable.
No, it is not possible for the moment to accomplish such a thing. What you seek is a feature missing for the moment, but it will be available with the 2.6 version of Redis. It's called LUA scripting. You can execute server commands that are dependent of previous commands, all in one, without the need to fetch them at the client. For more details see here.
Redis does not supports that directly, but this is very often demand in many cases. More generalized "atomic" pattern is:
Check multiple conditions
If all satisfied, run multiple commands
This can be acheived via simple lua script
-- Validate conditions and exec commands if ok
local params = cjson.decode(ARGV[1])
-- Check conditions
for __, check in pairs(params["if"]) do
if #check == 2 then
if check[1] ~= redis.call(unpack(check[2])) then return 0 end
elseif check[2] == "==" then
if check[1] ~= redis.call(unpack(check[3])) then return 0 end
elseif check[2] == "!=" then
if check[1] == redis.call(unpack(check[3])) then return 0 end
elseif check[2] == ">" then
if check[1] <= redis.call(unpack(check[3])) then return 0 end
elseif check[2] == "<" then
if check[1] >= redis.call(unpack(check[3])) then return 0 end
else
error('invalid operator "'..tostring(check[2])..'" (expected "==", "!=", ">" or "<")')
end
end
-- Eval redis commands
for __, exec in pairs(params["exec"]) do
redis.call(unpack(exec))
end
return 1
Then transaction details can be passed as simple JSON.stringify(object)
:
{
// Conditions. All must be satisfied
if: [
[ 'initialized', '==', [ 'sget', 'custom-state' ] ]
],
// Commands to execute if all conditions are satisfied
exec: [
[ 'set', 'custom-state', 'finished' ],
[ 'incr', 'custom-counter' ]
]
}
In many cases, such "conditional transactions" eliminate need of custom scripting.
See https://github.com/nodeca/redis-if for more samples / tests / src.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With