Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redis - Using Incr value in a transaction

Is it possible to use multi.incr(value) with multi.hmset?

I mean:

var name = 'Josh';
var multi = client.multi();
multi.incr('id'); // incr => 1
multi.hmset('user:' + <need incr value here>, 'username', name);
// I want multi.hmset('user:1', 'username', 'Josh');
multi.exec(function(err,data){ .. });

My objective is to increment 'id', and then set it to a user id in a transaction. I have read, that i need to do client.watch('id'), but i don't understand how to use it.

PD: Please, post your answer with code, is the best way :)

like image 729
robe007 Avatar asked Apr 20 '15 20:04

robe007


1 Answers

The accepted answer above is unnecessarily complicated. You do not need to use a multi or watch in this circumstance. INCR is already atomic, and is designed for this exact scenario. Edit: Thanks to Itamar Haber & robe007 for getting the accepted answer changed. :)

You can simply do this:

var name = 'Josh';
client.incr('id', function(err, id) {
    client.hmset('user:' + id, 'username', name);
});

By doing the above, INCR automatically locks the "id" key, increments it for you, unlocks it, and returns it to you. Thus, there is no way for anyone to get a duplicate user id using the code above. It also has the benefit of never really being able to fail, unlike WATCH/GET, where you'd have to check for failures and run your queries again if they failed.

like image 82
Ben Fried Avatar answered Sep 28 '22 00:09

Ben Fried