【发布时间】:2014-04-02 06:30:26
【问题描述】:
我正在运行一个竞赛网站,您可以在其中尝试点击数 X 来赢得奖品。它是用 Django 编写的,并在 Heroku 和 PostgreSQL 上运行。 每次点击都保存为 Play 模型的一个实例,它通过查看之前的 DB 中有多少次点击来计算它的数量,然后加 1。这个数字保存在 Play 模型中。这是整个网站的核心,因为您玩的次数决定了您是否中奖。
最近,我们遇到了一个2人同时中奖的案例。检查数据库,我发现实际上大约有 3% 的戏剧分享了他们的数字。哎呀。 我在 Play 模型的 'number' 和 'game' 字段中添加了 'unique_together',因此 DB 将帮助我避免将来出现重复的数字,但我很担心未来的比赛条件可能会使系统跳过一些数字,如果有问题的数字在哪里中奖,那就不好了。
我已经考虑锁定表,但担心这可能会破坏网站的并发性(我们目前有多达 500 名同时玩家,并且预计未来会更多)。
我应该实施什么策略来 100% 确定我从来没有重复或跳过数字?
我的游戏课:
class Play(models.Model):
token = models.CharField(unique=True, max_length=200)
user = models.ForeignKey(User)
game = models.ForeignKey(Game)
datetime = models.DateTimeField(auto_now_add=True)
winner = models.BooleanField(default=False)
flagged = models.BooleanField(default=False)
number = models.IntegerField(blank=True, null=True)
ip = models.CharField(max_length=200, blank=True, null=True)
def assign_number(self, x=1000):
#try to assign number up to 1000 times, in case of race condition
while x > 0:
before = Play.objects.filter(id__lt=self.id, game=self.game)
try:
self.number = before.count()+1
self.save()
x=0
except:
x-=1
class Meta:
unique_together = (('user', 'game', 'datetime'), ('game','number'))
【问题讨论】:
标签: python django postgresql heroku