2012-08-06 45 views
1

我有一個應該寫入redis實例的密鑰和一個值的列表(對於所有密鑰都是一樣的)。這應該只會發生,如果具有此項的條目已經存在。redis:設置是否存在 - 通過python

有一個MSETNX命令,這是做相反的:放在條目中,當鑰匙確實不存在存在。

當然,我可以通過EXIST之前檢查,並根據結果進行設置,但我如何確保這個原子。由於這個列表可能非常龐大,我該如何做這個基於管線的?

我使用redis-py作爲包裝,並且服務器上沒有可用的Lua腳本。

+1

使用[SETNX](http://redis.io/commands/setnx)創建鎖定。這將使您的所有操作成爲原子。 – freakish 2012-08-06 13:21:51

回答

2

這不是非常方便的沒有Lua,但它仍然可以使用WATCH/MULTI/EXEC命令完成。我們的想法是分割你巨大的鍵列表中的n項塊(N = 20爲例),然後應用下面的函數來每塊:

def process_block(redis_client, block, value): 
    with redis_client.pipeline() as pipe: 
     while True: 
      try: 
       pipe.watch(block) 
       to_set = [ for x in block if pipe.exists(x) ] 
       if to_set: 
        pipe.multi() 
        for x in to_set: 
         pipe.set(x, value) 
        pipe.execute() 
       break 
      except redis.WatchError: 
       continue 
      finally: 
       pipe.reset() 

原子性是由WATCH保證/ MULTI/EXEC命令,你將管道1 WATCH,1 MULTI,最多n SET和1 EXEC命令。不過,您將支付EXISTS往返費。爲n選擇正確的值是流水因子和併發交互風險之間的折中。它不應該設置得太高。

+0

不是我所期望的,但只要我不想更新,我就試試看。謝謝! – kraiz 2012-08-06 17:07:29

相關問題