我在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)'
解决方案的候选人我认为到目前为止:
- 我已阅读Django的文档有关的交易,但我不知道如何应用它们对我的问题。由于数据库不知道出价必须升序的要求,因此不会导致Django抛出IntegrityError。有没有在模型定义过程中定义这个约束的方法?还是它误解了交易API?
- 存储过程可以负责出价逻辑。这对我来说似乎是迄今为止“最好的”选择,但它将处理竞争条件转移到底层数据库系统。如果这是一个好方法,但是,这个解决方案可能与解决方案1相结合?
- 我考虑使用select_for_update调用来锁定此产品的出价。然而,这似乎并不是一个解决方案,因为在我的理解中,它不会影响任何新的竞价被创建?
愿望清单:
- 如果在任何可能的方式,我想从锁定整个表中标不要,因为其他产品的出价不能无论如何影响。
- 如果在应用程序级别上有一个很好的解决方案,我想让代码独立于底层的数据库系统。
非常感谢您的想法!
我不知道芹菜。感谢你!如果我的应用程序不会是“玩具”(阅读:小量的交易,..)我会考虑Celery肯定会实现可扩展性。 – Roland 2011-06-09 08:08:17