Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm using Node.js and Redis. I'm trying to come up with a reliable way to automatch players. There is a matching server and then multiple game servers set up.

The following is what I need to have happen:

  1. Player sends join request with game type (small/medium etc)
  2. Matching server adds player to the current game type that is waiting for players
  3. Game server sends player the game ID

Currently I have implemented this as follows:

  1. Matching server listens to game:queue:small using BRPOP
  2. Checks if game:queue:small:id = id exists
  3. Checks if game:id:users length is <= 6 (max players)
  4. Adds player to game:id:users list if it is
  5. If game length is now 6, it removes game:queue:small:id

If the matching server finds game:queue:small:id is missing, it does as follows:

  1. INCR game:nextGameId
  2. Sets game:queue:small:id to the previously generated ID
  3. Adds the game ID to game:queue:waiting

The game servers wait using BRPOP for new games. When they get one, they wait until the game has a minimum of 2 users then start a timer. If they don't fill up in that time, they begin with the users they have and subsequently remove game:queue:small:id (thus forcing the matchmaker to request a new game).

Whilst my method is working, I'm not convinced it will work well in production and it seems very convoluted. I can see the potential for the following issues:

  • Game server crashes after accepting the game ID from the waiting list resulting in users getting added to the game:id:users but nothing happening with them (the crash itself isn't a problem, but users continuing to get added to that games queue is)
  • If a user disconnects and the game hasn't started, the game server will remove the user from the game:id:users list. Whilst it is in the process of doing that, the matchmaking server could be adding a user to the list and think the game is full, thus removing it from the queue.

My initial thoughts were to change to a single queue of users waiting for one game type. However, this presents further issues:

  • If the server that the users connects to crashes, it won't remove the user from the queue thus leaving that user to be entered into a game when they don't exist. I could use sorted sets to store the time of the request and have the client poll until it gets a game ID returned but this would mean that I have no idea of how long that client has waited and therefore do not know whether to start the game with fewer users.
  • Without putting the users into a game, they have no ability to see what users have joined, nor the ability to chat with the users that are waiting (as that requires a game ID).

None of the way I have set this up feels right so I was hoping someone might be able to offer some better suggestions. I really need to keep the game servers and the matchmaking servers separate though in order to grow them out as required.

share|improve this question
    
The database issue I have resolved here: stackoverflow.com/questions/15172556/… –  Chris Evans Mar 2 '13 at 20:53
add comment

1 Answer

up vote 1 down vote accepted

Your first and foremost error is to use a database for a live queue, that data is much better off stored in process memory in the matchmaking process. Let the processes communicate with one another directly. Then it is also pretty much forced on you that it is the sole responsibility of the matchmaking server to remove players from the queue when they are put in a game, as it should be.

More generally about matchmaking, delay the decisions of what exact matches to make until the point where the game starts, if you have 3 players that fit a 4 player game, don't decide that they have to play that type of game before there is also a 4th player, it could take long for that player to arrive, and some of them might quit waiting in the meantime. A decent implementation for this is to have a queue for each game type and put each player in all queues matching their request, then when a queue is full start the game and remove the involved players from all of their queues.

share|improve this answer
    
I was using Redis as handles queues well. I was initially managing the matchmaking within the server itself and it worked very well but I found two issues with this approach: I couldnt' find a way to scale it out and secondly how does the server request a new game to start on another server. It could send out a message to them all but then the load wouldn't be balanced? –  Chris Evans Mar 2 '13 at 20:57
1  
@ChrisEvans You shouldn't worry too much about scaling, a simple matchmaking process can handle thousands of game initiations per second. If only you code it well you won't need the matchmaking to scale to multiple processes, even if you get millions of customers. As for balancing the load on the game servers a simple round robin approach where each game server get a new game in turn is reasonable effective if the servers are generally able to handle a large number of games each. Otherwise you can periodically ask the game servers how busy they are, it doesn't have to happen once per new game. –  eBusiness Mar 2 '13 at 22:32
    
Thanks. Appreciate the response. –  Chris Evans Mar 2 '13 at 22:38
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.