2012-06-11 2 views
3

Я использую пакет python (redis-py) для работы с базой данных redis. У меня есть куча клиентов, которые устанавливают ключи и значения хэша в redis. Я хочу, чтобы они устанавливали ключи и значения только тогда, когда существует хэш. Если хеш не существует, установка ключей и значений создаст хеш, чего я не хочу делать.Redis, разрешить операцию только для существующих ключей

На странице redis-py (https://github.com/andymccurdy/redis-py) автор предложил способ выполнять атомарную операцию на стороне клиента. Таким образом, я написал аналогичную функцию:

with r.pipeline() as pipe: 
     while True: 
      try: 
       pipe.watch("a_hash") 
       if pipe.exists("a_hash"): 
        pipe.hset("a_hash", "key", "value")     
       break 
      except redis.WatchError: 
       continue 
      finally: 
       pipe.reset() 

Однако, похоже, это не работает. После того, как я удаляю хэш из другого клиента, этот хэш по-прежнему создается с помощью этой части кода, поэтому я предполагаю, что этот фрагмент кода не является атомарной. Может ли кто-нибудь помочь мне определить, в чем проблема с этим кодом? Или лучше ли достичь этой цели?

Цените свою помощь!

ответ

4

Я бы предложил прочитать определение блока WATCH/MULTI/EXEC, как описано в Redis documentation.

В таком блоке только команды между MULTI и EXEC фактически обрабатываются атомарно (и условно, с семантикой «все или ничего» в зависимости от часов).

В вашем примере команды EXISTS и HSET не выполняются атомарно. На самом деле вам не нужна эта атомарность: вы хотите это условное исполнение.

Это должно работать лучше:

with r.pipeline() as pipe: 
    while True: 
     try: 
      pipe.watch("a_hash") 
      if pipe.exists("a_hash"): 
       pipe.multi() 
       pipe.hset("a_hash", "key", "value") 
       pipe.execute() 
      break 
     except redis.WatchError: 
      continue 
     finally: 
      pipe.reset() 

Если ключ будет удален после того, как СУЩЕСТВУЕТ, но до MULTI, то не будет H Установите быть выполнена, благодаря часам.

С Redis 2.6, Lua server-side script, вероятно, легче писать и более эффективно.

+0

Thanks Didier. Еще один вопрос: что, если ключ удаляется после multi? Поскольку redis выполняет команды очередей после multi, все еще выполняется hset в этой ситуации? – qkhhly

+0

Если ключ удаляется между MULTI и HSET или даже между HSET и EXEC, тогда блок MULTI/EXEC прерывается и HSET не применяется. –

+0

Требуется ли сброс() в этом примере? Документы говорят: «Если Pipeline используется в качестве диспетчера контекстного меню(), он будет вызван автоматически». –

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