我正在Django中实现一个eauction玩具应用程序,并且对于如何在下面的代码中最好地处理并发性感到困惑。我不确定哪些候选解决方案(或任何其他方案)最适合Django的设计。我是Django / python的新手,而且我的SQL专有技术是生锈的,所以如果这是一个不用脑子的道歉。
要求:用户可以对产品出价。只有在同一产品的出价高于之前的出价时才会接受出价。
以下是模型的精简版本:
class Product(models.Model):
name = models.CharField(max_length=20)
class Bid(models.Model):
amount = models.DecimalField(max_digits=5, decimal_places=2)
product = models.ForeignKey(Product)
和出价视图。这就是竞争条件发生的地方(见评论):
def bid(request, product_id):
p = get_object_or_404(Product, pk=product_id)
form = BidForm(request.POST)
if form.is_valid():
amount = form.cleaned_data['amount']
# the following code is subject to race conditions
highest_bid_amount = Bid.objects.filter(product=product_id).aggregate(Max('amount')).get('amount__max')
# race condition: a bid might have been inserted just now by another thread so highest_bid_amount is already out of date
if (amount > highest_bid_amount):
bid = Bid(amount=amount, product_id=product_id)
# race condition: another user might have just bid on the same product with a higher amount so the save() below is incorrect
b.save()
return HttpResponseRedirect(reverse('views.successul_bid)'
到目前为止我考虑的解决方案候选人:
非常感谢你的想法!
答案 0 :(得分:0)
你签出了Celery吗?您可以异步处理查询,对查询进行排队,然后在结果或错误可用时将其返回。如果你想避免锁定,这似乎是一条可能的路径。
否则,似乎需要进行一些锁定。
答案 1 :(得分:0)
您是否可以向highest_bid
添加Products
列。如果我的逻辑没有关闭,您可以更新最高出价where product_id = x and highest < current_bid
。如果此查询指示已更新行,则将新记录添加到出价表中。这可能意味着您必须拥有high_bid列的默认值。