2012-05-10 22 views
11

用於交易的文件說:Redis:爲什麼Lua腳本將取代交易?

「我們可能棄用並最終刪除交易」和「一切你 可以用Redis的交易做的,你也可以做一個劇本」

http://redis.io/topics/transactions

但是呢?我看到這個問題。

內可以觀看多個變量,讀這些變量交易,並根據你可以做一個完全不同的寫入調用exec前這些變量的唯一狀態。如果在這段時間內有任何干擾這些變量的狀態,EXEC將不執行該事務。 (它允許您重試。這是一個完美的交易系統。)

一個eval腳本不會讓你這樣做。根據此頁面上的文檔:

「腳本作爲純函數...腳本的結果總是相同的 Redis的編寫給予相同的輸入數據 組具有相同參數的命令腳本所執行的操作不能。依賴於任何隱藏 (非顯式)「可作爲腳本 執行前進或腳本的不同執行之間變化,也可以 它依賴於從I/O設備的任何外部輸入的信息或狀態。

http://redis.io/commands/eval

我EVAL看到的問題是,你不能讓那些變量的狀態腳本的內部,並根據這些變量的狀態了一套獨特的寫入。再說一遍:「腳本始終使用給定相同輸入數據集的相同參數來評估相同的Redis寫入命令。」所以結果寫入已經確定(從第一次運行緩存),並且EVAL腳本不關心腳本內部的GET值。你可以做的唯一事情就是在調用EVAL之前對這些變量執行GET,然後將這些變量傳遞給EVAL腳本,但是這裏有個問題:現在你在調用GET和調用EVAL之間存在原子性問題。

換句話說,所有你會做一個手錶交易,在EVAL的情況下,變量你,而不是需要讓這些變量,然後將它們傳遞到EVAL腳本。由於在腳本實際啓動之前腳本的原子性質不能得到保證,並且您需要在調用EVAL啓動腳本之前獲取這些變量,這會在GET和傳遞它們之間留下一個開頭,這些變量的狀態可能會發生變化EVAL。因此,對於一組非常重要的用例,您使用WATCH所具有的原子性保證不具有EVAL。

那爲什麼談自嘲事務時,將導致重要Redis的功能丟失?或者實際上有一種方法可以用我不明白的EVAL腳本來做到這一點?還是有計劃可以解決這個EVAL的功能? (假設的例子:如果他們做出與EVAL WATCH的工作,一起看EXEC作品以同樣的方式,可能的工作。)

有沒有解決辦法?或者我明白,從長遠來看,Redis可能不完全是交易安全的?

回答

15

它的確是lua腳本可以做任何交易,但我認爲Redis交易不會消失。

EVAL腳本不會讓你看變量

當一個eval腳本運行,沒有別的可以同時運行。所以,watch ing變量是毫無意義的。您可以確定沒有其他人在您讀取腳本中的值後修改了這些變量。

我EVAL看到的問題是,你不能讓那些變量的狀態腳本的內部,並根據這些變量的狀態了一套獨特的寫入。

不正確。您可以將密鑰傳遞給eval腳本。在您的eval腳本中,您可以從Redis讀取值,然後根據這些值有條件地執行其他命令。

該腳本仍然是確定性的。如果您將該腳本運行到從站上,它仍然會執行相同的寫入命令,因爲主站和從站具有相同的數據。

+0

如果你說的是基於實際經驗的話,那很好!它勝過了我對文檔的解釋:「腳本總是使用相同的輸入數據集來評估相同的Redis寫入命令。」對我而言,這意味着有一個緩存機制正在進行,以便第二次不會對腳本進行評估。它只是假定給定相同輸入的一組寫入。聽起來不確定。但是如果你有這方面的實際經驗,我會推薦你​​的專業知識,我感謝你的回答。 – OCDev

+1

此外,關於我的假設示例,我正在討論一個假設功能,其中WATCH可用於* EVAL外的*和* EVAL執行前的*。 (從這個意義上來說,EVAL的行爲類似於EXEC的新功能。)這樣,可以執行GET準備將它們傳遞給EVAL,而不必擔心它們發生變化。 (儘管如此,如果EVAL內部仍然是確定性的,那麼模糊一點。)再次感謝。 :) – OCDev

+0

Redis DB Server在Transaction(MULTI/EXEC)和Eval之間發生故障時會發生什麼?假設幾條命令像POP/PUSH一樣執行......並在執行更多命令之前關閉。 –

12

EVAL腳本實​​際上擴展並簡化了事務的功能。

它可以幫助查看兩類交易在Redis的下列方式:

1.程序(MULTI EXEC)

純MULTI EXEC是分組命令一氣呵成被執行並從每個命令返回一組響應。它有一個嚴重的限制。它不允許允許使用來自一個命令的中間結果在下一個內的的事務中。在這種純粹的形式中,它在實際應用中並不是非常有用。它基本上是一個保證原子性的流水線。

在事務處理之前添加WATCH 密鑰,允許進行樂觀鎖定並在事務中使用Redis以外的事務中獲取的值。如果競賽狀況發生,交易失敗並且必須重試。這使得應用程序邏輯變得複雜,並且樂觀往往沒有根據,因爲你可能會在無盡的重試循環中結束。

2.功能(EVAL腳本)

EVAL不僅分組Redis命令,但也爲您提供了完整的編程語言,特別是條件,功率循環和局部變量。在Lua腳本中,您可以通過一個命令從Redis中讀取值,並在稍後的命令中使用它們。

您提交以原子方式執行的腳本。它由單線程保證,「停止世界」的方法。執行腳本時不會執行其他腳本或Redis命令。因此,EVAL也有一個限制:腳本必須小而快,以防止阻止其他客戶端。

我們還需要相信其他客戶端不會提交應該被視爲編程錯誤的慢腳本。它適用於安全模型,因爲「Redis旨在被信任環境中的可信客戶訪問」

+0

Redis DB Server在Transaction(MULTI/EXEC)和Eval之間發生故障時會發生什麼?假設幾條命令像POP/PUSH一樣執行......並在執行更多命令之前關閉。 –