Reputation: 7107
I'm new to redis
, but from reading the docs I couldn't find if it is possible to update a value with a query (like mongo
or postgres
).
For example, I want to execute some logic for players in the lobby. I want to update the user status to lobby
only if it was in home
.
Applying this logic in the app won't work since I may encounter a race condition between 2 processes.
I would do something like this in mongo:
update({id:1, status:home}, {status: lobby})
This way I will receive the result (success or fail) if the update was successful, and it is atomic.
How can I do it in redis
?
Upvotes: 0
Views: 1277
Reputation: 2969
You can do it in a LUA procedure:
eval "local ks=redis.call('keys','user:*') for k=1,#ks do print(k) if (redis.call('hget',ks[k],'status') == KEYS[1]) then redis.call('hset',ks[k],'status',KEYS[2]) end end" 2 home lobby
127.0.0.1:6370> hset user:1 id 1 (integer) 1
127.0.0.1:6370> hset user:1 status outside (integer) 1
127.0.0.1:6370> hset user:2 id 2 (integer) 1
127.0.0.1:6370> hset user:2 status home (integer) 1
127.0.0.1:6370> eval "local ks=redis.call('keys','user:*') for k=1,#ks do print(k) if (redis.call('hget',ks[k],'status') == KEYS[1]) then redis.call('hset',ks[k],'status',KEYS[2]) end end" 2 home lobby
(nil)
127.0.0.1:6370> hgetall user:2 1) "id" 2) "2" 3) "status" 4) "lobby"
127.0.0.1:6370> hgetall user:1 1) "id" 2) "1" 3) "status" 4) "outside"
Upvotes: 0
Reputation: 3063
There's no update-by-query in Redis, like in other document stores/RDBMSs
You can either go with MULTI-EXEC transactions or EVAL / EVAL SHA to perform atomic updates and compose a batch of commands together
Redis uses a single thread for command processing (as of this moment), so evaluating a script would be performed atomically, and would probably be more straight forward approach than multi-exec.
Upvotes: 1