Существует много тем о параллелизме Django, но после проверки многих из них я не чувствую, что нашел свой ответ, когда дело доходит до транзакций.
Django версия 1.3.1.Postgresql версия 8.4.7.
Очень простая версия моих моделей может выглядеть так:
def Member(Model):
money = PositiveIntegerField(default=0)
user = OneToOneField(User, related_name='member', primary_key=True)
def Bet(Model):
total_money = PositiveIntegerField(default=0)
У меня также есть таблица Money, которая является отношением между Участником и Bet.Это не связано напрямую с моей проблемой, но помогает мне контролировать ее, потому что на нее не могут повлиять проблемы параллелизма.то есть я просто должен посчитать свою таблицу Money, чтобы проверить правильность полей money of Member и total_money of Bet.
Хотя я не могу полагаться только на таблицу Money, и мне нужно, чтобы мои поля были правильнымипотому что я много фильтрую, используя их.
Моя первая попытка использования функции ставки была примерно такой (просто с гораздо большим количеством модификаций для намного большего количества таблиц).
def bid(user_pk, bet_pk, value):
#create Money object
member = User.objects.get(user_pk).member
member.money = F('money') - value
member.save()
bet = Bet.objects.get(bet_pk)
bet.total_money = F('total_money') + value
bet.save()
ЭтоВерсия работала очень хорошо, пока я не получил мой первый сбой во время одной транзакции.Мне также пришлось скопировать и вставить все тесты из моих функций clean () в bid (), потому что я в действительности не могу использовать clean () или full_clean () в этом случае (особенно если ставка повышается после сохранения участника).
Поэтому я решил попробовать транзакцию django.
@transaction.commit_manually
def bid(user_pk, bet_pk, value):
try:
#create money object
member = User.objects.get(user_pk).member
member.money -= value
member.clean()
member.save()
bet = Bet.objects.get(bet_pk)
bet.total_money += value
bet.clean()
bet.save()
except:
transaction.rollback()
raise
else:
transaction.commit()
Но без возможности использовать объект F () внутри ручной транзакции (что имеет смысл).Я столкнулся с множеством проблем с параллелизмом.
Я вижу только два решения:
Создайте только объекты Money во время bid () / транзакции, затем используйте асинхронныйработник (Celery?), который обновляет соответствующие поля в Member и Bet.
Создайте список заявок () / транзакции (Redis?) и выполните все транзакции, которые изменяют поля, связанные с деньгами.синхронный.
Я упускаю очевидное и более простое решение?Если нет, какое решение вы бы порекомендовали, используя какую технологию?