我在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