Requests synchronization on multiple servers

We have an API for a game on Django Rest Framework. There are tournaments and tournament participants in the game. Tournament model has the max_players field and the API should not allow register more participants when max_players number is reached.

This is simplified models:

class Tournament(models.Model):
    max_players = models.PositiveIntegerField()

class TourneyPlayer(models.Model):
    tourney = models.ForeignKey(Tourney, on_delete=models.CASCADE, related_name='players')
    user = models.ForeignKey(User, on_delete=models.CASCADE)

There is serializer in the registration endpoint and within its validate method it checks the number of already registered players returns an error if the tourney is full:

def validate(self, attrs):
    if tourney.players.count() >= tourney.max_players:
        raise serializers.ValidationError()
    return attrs

And if validation passes we create a new TourneyPlayer object.

But when we create a new tournament all users receive notification and many of them immediately click on the register button. It causes a lot of requests at the same time and sometimes player is being registered even when max_player count reached. It happens because there is some delay between validation and creation, so the classic concurrency issue arises:

Request A validated Request B validated Request A created player Request B created player

Locally I solved this issue by adding the threading.Lock object, but how to do it if we have multiple servers behind the load balancer? I think to use Redis, write some value when registration request starts and clear this value when it finishes. And if the value already set, check it in a loop with some interval using sleep function. But maybe there are better solutions?

Back to Top