2012-02-04 2 views
0

Я пытаюсь использовать redis для блокировки некоторых крупных транзакций Postgresql управления, которые у меня есть в моем проекте. Я пока не добился успеха в своей среде разработки.Django, используйте redis-py для блокировки в представлении django

Простой вариант кода будет выглядеть так:

def test_view(request): 
    connec = redis.Redis(unix_socket_path='/tmp/vgbet_redis.sock') 
    if not connec.setnx('test', ''): 
    print 'Locked' 
    else: 
    time.sleep(5) #Slow transaction 
    connec.delete('test') 
    print 'Unlocked' 
    return render_to_response("test.html") 

Если открыть две вкладки этой точки зрения, первая печать разблокирована после 5 секунд, а затем второй печатает разблокирована после 10 секунд. Похоже, они синхронны, что не имеет для меня никакого смысла.

Редактировать: Я попытался установить apache и gevent, и я получил точные результаты.

Так что я думаю, что с django + redis я действительно не понимаю, и мой код действительно неправильный.

Любая помощь будет отличной.

Редактировать2: Я просто попытался использовать django-redis, используя redis в качестве кеша.

CACHES = { 
    'default': { 
    'BACKEND': 'redis_cache.RedisCache', 
    'LOCATION': '/tmp/vgbet_redis.sock', 
    'OPTIONS': { 
     'DB': 1, 
     'PASSWORD': None, 
     'PARSER_CLASS': 'redis.connection.HiredisParser' 
    }, 
    }, 
} 

И все же у меня есть тот же результат, если я открою две вкладки в своем браузере. Второй вид заблокирован на 5 секунд, как будто все синхронно.

from django.core.cache import cache 
def test_view(request): 
    if cache.get('test') != None: 
    print 'Locked' 
    else: 
    cache.set('test', '', 60) 
    time.sleep(5) #Slow transaction 
    cache.delete('test') 
    return render_to_response("test.html") 

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

+0

Следует отметить: замки, которые у вас там, не будут атомарными. Было бы лучше использовать [setnx] (http://redis.io/commands/setnx), что помешало бы условиям гонки. –

+0

Я обновил свой код, спасибо. – Ashe

ответ

0

Основная причина моей проблемы заключалась в том, что я использовал две вкладки в своем браузере. Если я использую два браузера или два разных IP, мой код работает асинхронно (с gevent и apache, а не с сервером, но это не удивительно).

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

+0

А это может быть связано с тем, что ваш веб-браузер откроет определенное количество подключений к определенному серверу в любое время. Какой браузер вы используете? –

+0

Интересно, Chrome 16 – Ashe

+0

Ах, странно. Это должно позволить по крайней мере два соединения. –

2

Пару вещей, чтобы проверить:

  • По умолчанию сервер разработки Django является однопоточных, так может обрабатывать только один запрос одновременно. Самый простой способ проверить это - запустить сервер разработки дважды на разных портах (например, ./manage.py runserver 8080 и ./manage.py runserver 8081).
  • Если вы используете базу данных SQL вообще, то может блокировать транзакцию. Изображения того же автора: Фотографии Вы используете это? Или вы делаете что-нибудь с моделями?
  • Вы упомянули, используя gevent - вы не забыли позвонить from gevent import monkey; monkey.patch_all() для обезьян патч все? Кроме того, как вы используете свой сервер с gevent?
+0

Я, наконец, нашел свою ошибку, я только что опубликовал ответ. Большое спасибо за ваш ответ, мне нравится совет по использованию двух серверов, и я обязательно буду следовать вашей рекомендации по обновлению gevent. – Ashe

+0

Вы бы рекомендовали вызвать redis.Redis (...) во всех представлениях или создать глобальный? Что-то меняет? – Ashe

+0

Вы должны создать глобальный. 'Redis' (при условии, что вы используете' redis-py'), хранится внутренний пул потоков, поэтому нет причин не делать его глобальным, и сделать его глобальным потенциально ускоряет работу (поскольку новое TCP-соединение не будет необходимо устанавливать каждый раз). –

Смежные вопросы