Лучший подход для управления параллелизмом в Django для eauction toy-app - PullRequest
4 голосов
/ 09 июня 2011

Я реализую игрушечное приложение для Eauction в Django, и я не совсем понимаю, как лучше всего обрабатывать параллелизм в приведенном ниже коде. Я не уверен, какой из моих кандидатов на решение (или любой другой) лучше всего подходит для дизайна 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)'

Кандидаты на решение, которые я рассматривал до сих пор:

  1. Я прочитал документ Django о транзакциях, но я не знаю, как применить их к моей проблеме. Поскольку база данных не знает о требовании повышения ставок, она не может заставить Django выдать IntegrityError. Есть ли способ определить это ограничение во время определения модели? Или он неправильно понял API транзакции?
  2. Хранимая процедура может позаботиться о логике назначения ставок. Пока это кажется мне «лучшим» выбором, но он переносит обработку состояния гонки на базовую систему баз данных. Однако, если это хороший подход, это решение может быть объединено с решением 1?
  3. Я подумал об использовании вызова select_for_update для блокировки ставок для этого продукта. Однако это, похоже, не является решением, поскольку, насколько я понимаю, это не повлияет на создание новых ставок?

Список пожеланий:

  • Если есть какая-либо возможность, я бы хотел не блокировать всю таблицу ставок, поскольку ставки на другие продукты не могут быть затронуты в любом случае.
  • Если есть хорошее решение на уровне приложения, я хотел бы сохранить код независимым от базовой системы баз данных.

Большое спасибо за ваши мысли!

Ответы [ 2 ]

0 голосов
/ 09 июня 2011

Можно ли добавить highest_bid столбец к Products. Если моя логика не выключена, вы можете обновить самую высокую ставку where product_id = x and highest < current_bid. Если этот запрос показывает, что строка была обновлена, вы добавляете новую запись в таблицу ставок. Это, вероятно, будет означать, что вам нужно иметь значение по умолчанию для столбца самая высокая_бид.

0 голосов
/ 09 июня 2011

Вы проверили Сельдерей ?Вы можете обрабатывать свои запросы асинхронно, ставить их в очередь и затем возвращать результаты или ошибки, когда они становятся доступными.Это выглядит как вероятный путь, если вы хотите избежать блокировки.

В противном случае, похоже, что потребуется некоторая блокировка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...