2016-07-06 36 views
1

我有一個由多個節點組成的redis集羣。我想在單個原子操作中更新3個不同的鍵。我的Lua腳本是這樣的:Redis集羣:使用Lua腳本更新不同節點中的密鑰

local u1 = redis.call('incrby', KEYS[1], ARGV[1]) 
local u2 = redis.call('incrby', KEYS[2], ARGV[1]) 
local u3 = redis.call('incrby', KEYS[3], ARGV[1]) 

和我一起放了一槍:

EVAL script 3 key1 key2 key3 arg 

但我得到WARN Resp(AppErr CROSSSLOT Keys in request don't hash to the same slot)。上述操作無法完成,更新將失敗。看來我不能用一個Lua腳本修改不同節點中的密鑰。但根據文檔:

執行前必須分析所有Redis命令,以確定 命令將操作哪些鍵。爲了確保EVAL爲 ,必須明確傳遞密鑰。這在很多方面都很有用, ,但特別要確保Redis羣集可以將您的請求轉發到 適當的羣集節點。

注意這條規則並不是爲了 向用戶提供有機會濫用Redis的單 實例配置,在寫劇本不兼容 與Redis的集羣的成本執行。

所以我認爲只要遵循按鍵傳遞規則,腳本應該與redis集羣兼容。我想知道這裏有什麼問題,以及我應該如何更新單個腳本中的所有密鑰。

回答

4

恐怕你誤解了文檔。 (我同意它不是很清楚。)

Redis操作,無論命令還是Lua腳本,只能在所有密鑰位於同一臺服務器上時才能使用。密鑰傳遞規則的目的是讓羣集服務器找出腳本的發送位置,如果所有密鑰不是來自同一個服務器(發生在您的案例中),則快速失敗。

因此,您有責任確保您要操作的所有密鑰位於同一臺服務器上。要做到這一點的方法是使用散列標記強制密鑰散列到同一個插槽。有關更多詳情,請參閱the documentation

+0

我明白了。我使用羣集的原因是希望不同的密鑰在不同的節點中進行縮放。所以在這種情況下,我可能會放棄以原子方式更新密鑰。非常感謝。 –

+0

很好的解釋,謝謝! – Till

+1

也許我有點晚,但我有一個後續問題: 如果我確定未指定的密鑰在同一個羣集上,我仍然可以使用Lua腳本嗎?所以我打破了必須指定所有密鑰的規則,但遵循所有密鑰都在同一臺服務器上的規則。 – user3688217