Есть такая задача:
нужно собирать статистику показов рекламы на сайте, чтобы не дергать на каждый показ базу решил держать джанговский объект в memcached, и сохранять в базу через каждые 1000 показов.
Вот тут и появляется проблема, процессов с джангой запущено несколько десятков, и при каких-то условиях (так и не понял при каких), на email приходит traceback с ошибкой при вызове save() для сохранения статистики в базу с сообщением “IntegrityError: duplicate key value violates unique constraint ”unique_together“”.
код следующий:
bstat = cache.get(cache_key)
if not bstat:
# получаем/создаем объект статистики для данного баннера
try:
bstat = BannerStatistic.objects.get(year=year, month=month, day=day, banner=banner)
except BannerStatistic.MultipleObjectsReturned:
bstat = BannerStatistic.objects.filter(year=year, month=month, day=day, banner=banner).order_by('id')[0]
except BannerStatistic.DoesNotExist:
bstat = BannerStatistic()
bstat.year, bstat.month, bstat.day = year, month, day
bstat.banner = banner
bstat.banner_clicks = 0
bstat.banner_shows = 0
bstat.banner_CTR = 0
# обновляем статистику по кликам/показам
if action == 'show':
bstat.banner_shows += 1
elif action == 'click':
bstat.banner_clicks += 1
# сохраняем в базу каждые N показов или при каждом клике, до этого держим в memcached
if settings.DEBUG:
SAVE_SHOWS_CONDITION_COUNT = 1
else:
SAVE_SHOWS_CONDITION_COUNT = 1000
if (bstat.banner_shows % SAVE_SHOWS_CONDITION_COUNT == 0) or (action == 'click'):
bstat.save()
(соответственно собирается новая статистика за день,
т.е. объектов за сегодня пока еще не создавалось в базе):
процесс1 попробовал получить из кэша статистику, не нашел, в базе тоже не нашел, создал новый объект
процесс2 в это время сделал тоже самое, т.к. в базе и кэше пока такого объекта нет
процесс1 сохранил в базу и кэш объект
процесс2 попытался сохранить тоже в базу объект и нарвался на ошибку
вот, собственно вопрос, как решить данную задачу?
нужен какой-то Lock manager?
multiprocessing тут насколько я понял не поможет, т.к. общего родителя у процессов нет.
Буду благодарен за любую помощь и отсылки куда копать.
Спасибо.