Search code examples
redisatomicmultiplayer

SADD only if SCARD below a value


Node.js & Redis:

I have a LIST (users:waiting) storing a queue of users waiting to join games.

I have SORTED SET (games:waiting) of games waiting for users. This is updated by the servers every 30s with a new date. This way I can ensure if a server crashes, the game is no longer used. If the server is running and fills up, it'll remove itself from the sorted set.

Each game has a SET (game:id:users) containing the users that are in it. Each game can accept no more than 6 players.

Multiple servers are using BRPOP to pick up users from the LIST (users:waiting).

Once a server has a user id, it gets the waiting games ids, then proceeds to run SCARD on their game:id:users SET. If the result of this is less than 6, it adds them to the set.

The problem:

If multiple servers are doing this at once, we could end up with more than 6 users being added to a set at a time. For example if one server requests SCARD and immediately after another runs SADD, the number in the set will have increased but the first server won't know.

Is there anyway of preventing this?


Solution

  • You need transactions, which redis supports: http://redis.io/topics/transactions

    in your case in particular, you want to pay attention to the watch command: http://redis.io/topics/transactions#cas