4

I'm developing a tournament version of a game where I expect 1000+ simultaneous players. When the tournament begins, players will be eliminated quite fast (possibly more than 5 per second), but the process will slow down as the tournament progresses. Depending when a player is eliminated from the tournament a certain amount of points is awarded. For example a player who drops first, gets nothing, while player who is 500th, receives 1 point and the first place winner receives say 200 points. Now I'd like to award and display the amount of points right away after a player has been eliminated.

The problem is that when I push a new row into a datastore after a player has been eliminated, the row entity has to be in a separate entity group so I would not hit the gae datastore limit of 1-5 writes per second for 1 entity group. Also I need to be able to read and write a count of rows consistently so I can determine the prize correctly for all the players that get eliminated.

What would be the best way to implement the datamodel to support this?

jaz
  • 121
  • 1
  • 2
  • 10
  • Are there ties, or are the results a strict totally ordered set? What is the total duration of a game, or put another way how will the players complete the game? Do the game completions follow something that looks like an exponential, uniform, normal, or beta distribution? – Robert Kluin Dec 19 '10 at 19:00
  • There are no ties. The tournament ends when there is only 1 player left and there must always be a strict order regarding elimination. The prize pool distribution will be calculated the moment, the tournament starts. Think of a Texas Hold 'em tournament. – jaz Dec 19 '10 at 19:10
  • In a Texas Holdem tournament, the tables move to hand-by-hand play when more than one person is all-in - otherwise, there'd be no way to determine who really went out first when two tables eliminate people more or less simultaneously. – Nick Johnson Dec 19 '10 at 22:57

2 Answers2

2

Since there's a limited number of players, contention issues over a few a second are not likely to be sustained for very long, so you have two options:

  1. Simply ignore the issue. Clusters of eliminations will occur, but as long as it's not a sustained situation, the retry mechanics for transactions will ensure they all get executed.
  2. When someone goes out, record this independently, and update the tournament status, assigning ranks, asynchronously. This means you can't inform them of their rank immediately, but rather need to make an asynchronous reply or have them poll for it.

I would suggest the former, frankly: Even if half your 1000 person tournament went out in the first 5 minutes - a preposterously unlikely event - you're still looking at less than 2 eliminations per second. In reality, any spikes will be smaller and shorter-lived than that.

One thing to bear in mind is that due to how transaction retries work, transactions on the same entity group that occur together will be resolved in semi-random order - that is, it's not a strict FIFO queue. If you require that, you'll have to enforce it yourself, though that's a far from trivial thing to do in a distributed system of any sort.

Nick Johnson
  • 100,655
  • 16
  • 128
  • 198
  • Thanks Nick, good to see you :) I will go with the 1st options for now, but for future reference and perhaps for others, who might have a similar problem, lets assume for now that I'll go with option 2. I'd insert a row each time a player is eliminated and then the asynchronous task would assign ranks and move these rows to a collection in tournament entity every once in a while. How would you run the asynchronous task to do that? I would probably use a task queue with memcache to make sure a tasks for 1 tournament will not be queued more than once a second. – jaz Dec 20 '10 at 10:50
  • @jaz Use named tasks, named after the time interval in which they execute. – Nick Johnson Dec 20 '10 at 20:24
0

the existing comments and answers address the specific question pretty well.

at a higher level, take a look at this post and open source library from the google code jam team. they had a similar problem and ended up developing a scalable scoreboard based on the datastore that handles both updates and requests for arbitrary pages efficiently.

ryan
  • 2,687
  • 1
  • 29
  • 38