Redis Lua指令碼編寫快速指南

2021-10-12 20:57:19 字數 4444 閱讀 8227

您應該在系統上安裝redis才能執行本文中的例子。閱讀本文時對照redis命令參考可能會更有幫助。

簡而言之:效能提公升。您在redis中執行的大多數任務都涉及許多步驟。您可以使用lua在redis內部進行操作,而不必使用應用程式語言來執行這些步驟。

例如,我使用lua指令碼改變儲存在redis的json字串。我將在本文後半部分對此進行詳細描述。

乙個不認識lua的人

別擔心,lua並不是很難理解。如果您了解c語言系列中的任何語言,那麼您應該很容易上手lua。另外,我在本文中提供了**示例。

讓我們開始通過redis-cli執行指令碼。從以下內容開始:

redis-cli
現在執行以下命令:

eval 「redis.call(『set』, keys[1], ar**[1])」 1 key:name value
eval命令就是告訴redis的執行下面的指令碼。該」redis.call(『set』, keys[1], ar**[1])」字串是我們的指令碼,其功能與redis的set命令相同。指令碼文字後面跟隨三個引數:

鍵的個數

鍵名鍵值

指令碼引數分為兩類:keysar**

我們用緊隨其後的數字指定指令碼需要多少個鍵。在我們的示例中,該值為1。在此編號之後,我們需要立即接這些key。它們可以作為指令碼中的keys表訪問。在我們的例子中,它key:name在索引1處包含乙個值。

注意,lua索引表從索引1開始,而不是0

我們可以在鍵之後提供任意數量的引數,這些引數可以在lua中作為ar**表使用。在此示例中,我們提供了乙個ar**引數:stringvalue。您已經猜到了,上面的命令將鍵設定key:name為valuevalue

提供指令碼使用的key作為keys以及提供所有其他引數作為ar**是一種好習慣。因此,您不應該將keys指定為0,然後在ar**表中提供所有key。

現在讓我們檢查指令碼是否成功完成。我們將通過執行另乙個從redis獲取金鑰的指令碼來做到這一點:

eval 「return redis.call(『get』, keys[1])」 1 key:name
輸出應該為」value」,這意味著先前的指令碼成功設定了鍵值 「key:name」`。

我們的第乙個指令碼包含乙個語句:redis.call函式:

redis.call('set',keys [1],ar** [1])
使用redis.call它可以執行任何redis命令。第乙個引數是此命令的名稱,後跟其引數。對於set命令,這些引數是keyvalue。支援所有redis命令。根據文件:

redis使用相同的lua直譯器來執行所有命令

我們的第二個指令碼不僅僅執行乙個命令,它還返回乙個值:

eval 「return redis.call(『get』, keys[1])」 1 key:name
指令碼返回的所有內容都傳送到呼叫過程。在我們的情況下,此過程為redis-cli,您將在終端視窗中看到結果。

我曾經使用lua指令碼以特定順序從雜湊對映中返回元素。順序是儲存在有序集order鍵中。

首先,通過在redis-cli中執行以下命令來設定資料:

hmset hkeys key:1 value:1 key:2 value:2 key:3 value:3 key:4 value:4 key:5 value:5 key:6 value:6

zadd order 1 key:3 2 key:1 3 key:2

這條命令處建立了乙個名為:hkeys的雜湊對映,filed名為:key:*** ,order其中包含hkeys按特定順序從中選擇filed。

您可能需要檢視

hmset

和zadd

命令參考以獲取詳細資訊。

讓我們執行以下指令碼:

eval 「local order = redis.call(『zrange』, keys[1], 0, -1)

;return redis.call(『hmget』,keys[2],unpack(order))

;」 2 order hkeys

您應該看到以下輸出:

「value:3」

「value:1」

「value:2」

這意味著我們以正確的順序獲得了所需hash filed的值。

redis允許您使用script load命令將指令碼預載入到記憶體中:

script load 「return redis.call(『get』, keys[1])」
您應該看到如下輸出:

「4e6d8fc8bb01276962cce5371fa795a7763657ae」
這是您需要提供給evalsha命令以執行指令碼的指令碼的唯一雜湊:

evalsha 4e6d8fc8bb01276962cce5371fa795a7763657ae 1 key:name
注意:您應該使用script load命令返回的實際sha1雜湊,上面的雜湊只是乙個示例。

有時人們在redis中儲存json物件。可以檢視我前面一篇文章的講解《redis使用字串和hash儲存json,那個更高效?》。

如果必須在此json物件中更改key,則需要從redis中獲取key的value值,然後對其進行解析,更改key的value值,然後進行序列化並將其設定回redis。這種方法存在兩個問題:

併發。另乙個過程可以在我們的get和set操作之間更改此json。在這種情況下,更改將丟失。

效能。如果您經常進行這些更改,並且json物件很大,則可能成為應用程式的瓶頸。您可以通過在lua中實現此邏輯來提高一些效能。

讓我們在key下的redis中新增乙個測試json字串obj

set obj 『』
現在執行指令碼:

eval 『local obj = redis.call(「get」,keys[1]

); local obj2 = string.gsub(obj,」(「 .. ar**[1]

.. 「\」:)

([^,}

]+)」, 「%1」 .. ar**[2]);

return redis.call(「set」,keys[1],obj2)

;』 1 obj b bar2

現在我們將在key下具有以下物件obj

您可以使用script load命令來載入此指令碼,然後像這樣執行它:

evalsha 1 obj b bar2
一些注意事項:不。我建議僅在可以證明它可以帶來更好的效能時才使用它們。首先都要做基準測試,確定效能會提高才需要使用lua指令碼。如果您只需要原子性,則應改為檢查redis事務。

另外,您的指令碼不應太長。請記住,指令碼執行時,其他所有內容都在等待指令碼完成。如果您的指令碼需要花費一些時間,則可能會導致瓶頸,而不是提高效能。指令碼在達到超時(預設為5秒)後停止。有關lua的更多資訊,請訪問lua.org。

REDIS LUA指令碼使用經驗分享

redis lua指令碼出現之前redis是沒有伺服器端運算能力的,主要是用來儲存,用做快取用,運算是在客戶端進行,這樣帶來了很大的頻寬流量。lua出現之後這一問題得到了充分的解決,非常棒!redis lua指令碼api介紹 eval 在redis伺服器端執行lur指令碼 evalsha 在redi...

Redis Lua指令碼實現復合操作原子化

redis是高效能的key value資料庫,在很大程度克服了memcached這類key value儲存的不足,在部分場景下,是對關聯式資料庫的良好補充。得益於超高效能和豐富的資料結構,redis已成為當前架構設計中的首選key value儲存系統。雖然redis官網上提供了200多個命令,但做程...

居於redis lua指令碼實現的滑動視窗

我們常常使用滑動視窗實現限流操作,在單機時我們經常放在記憶體中實現,而在做全域性介面限流時,我們除了可以通過查詢介面呼叫記錄外,還可以通過依賴redis實現的滑動視窗進行,比如限制1分鐘可呼叫1000次,一小時可呼叫10000次。1 乙個固定長度的迴圈佇列 2 每個時間片的時長,可以是按秒 分 時。...