2011-06-08 67 views
4

我在Django中实现了一个eauction玩具应用程序,并且对如何在下面的代码中最好地处理并发性感到困惑。我不确定我的解决方案候选人(或任何其他人)对Django的设计最适合。我对Django/python相当陌生,而且我的SQL知识很生疏,所以如果这是一件不容易的事情,我很抱歉。在Django中处理并发的最佳方法eauction玩具-app

要求:用户可以对产品进行出价。只有在投标高于之前对同一产品的投标时,投标才被接受。

这里是模型的一个精简版:

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)' 

解决方案的候选人我认为到目前为止:

  1. 我已阅读Django的文档有关的交易,但我不知道如何应用它们对我的问题。由于数据库不知道出价必须升序的要求,因此不会导致Django抛出IntegrityError。有没有在模型定义过程中定义这个约束的方法?还是它误解了交易API?
  2. 存储过程可以负责出价逻辑。这对我来说似乎是迄今为止“最好的”选择,但它将处理竞争条件转移到底层数据库系统。如果这是一个好方法,但是,这个解决方案可能与解决方案1相结合?
  3. 我考虑使用select_for_update调用来锁定此产品的出价。然而,这似乎并不是一个解决方案,因为在我的理解中,它不会影响任何新的竞价被创建?

愿望清单:

  • 如果在任何可能的方式,我想从锁定整个表中标不要,因为其他产品的出价不能无论如何影响。
  • 如果在应用程序级别上有一个很好的解决方案,我想让代码独立于底层的数据库系统。

非常感谢您的想法!

回答

0

您是否已退房Celery?您可能会异步处理查询,排队查询,然后在结果或错误可用时返回。如果你想避免锁定,这似乎是一个可能的途径。

否则,它看起来好像需要发生一些锁定。

+0

我不知道芹菜。感谢你!如果我的应用程序不会是“玩具”(阅读:小量的交易,..)我会考虑Celery肯定会实现可扩展性。 – Roland 2011-06-09 08:08:17

0

是否可以将highest_bid列添加到Products。如果我的逻辑没有关闭,您可以更新最高出价where product_id = x and highest < current_bid。如果此查询表明某行已更新,则您将新记录添加到出价表中。这可能意味着您必须为highest_bid列设置默认值。

+0

谢谢!这将做到这一点。它不仅限制了单行上的数据库锁定,而且还允许我摆脱丑陋的聚合函数,以计算上面示例代码中当前的'highest_bid'。 – Roland 2011-06-09 08:03:06

相关问题