

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# Lua 指令碼
<a name="BestPractices.Clients.Redis.LuaScripts"></a>

Valkey 和 Redis OSS 支援超過 200 個命令，包括執行 Lua 指令碼的命令。不過，在 Lua 指令碼方面，有幾個陷阱可能會影響 Valkey 或 Redis OSS 的記憶體和可用性。

**未參數化的 Lua 指令碼**

每個 Lua 指令碼都會在執行之前快取在 Valkey 或 Redis OSS 伺服器上。無參數 Lua 指令碼是唯一的，這可能會導致 Valkey 或 Redis OSS 伺服器存放大量 Lua 指令碼並耗用更多記憶體。為了緩解這種情況，務必確保所有 Lua 指令碼皆參數化，並且在需要時定期執行 SCRIPT FLUSH 來清除快取的 Lua 指令碼。

另請注意，必須提供金鑰。如果未提供 KEY 參數的值，指令碼將會失敗。例如，這將無法運作：

```
serverless-test-lst4hg.serverless.use1.cache.amazonaws.com:6379> eval 'return "Hello World"' 0
(error) ERR Lua scripts without any input keys are not supported.
```

這將可運作：

```
serverless-test-lst4hg.serverless.use1.cache.amazonaws.com:6379> eval 'return redis.call("get", KEYS[1])' 1 mykey-2
"myvalue-2"
```

以下範例說明如何使用參數化指令碼。首先將示範非參數化的方法來產生三個不同的已快取 Lua 指令碼，這是不建議的方法：

```
eval "return redis.call('set','key1','1')" 0
eval "return redis.call('set','key2','2')" 0
eval "return redis.call('set','key3','3')" 0
```

建議改用下列模式來建立可接受所傳遞參數的單一指令碼：

```
eval "return redis.call('set',KEYS[1],ARGV[1])" 1 key1 1 
eval "return redis.call('set',KEYS[1],ARGV[1])" 1 key2 2 
eval "return redis.call('set',KEYS[1],ARGV[1])" 1 key3 3
```

**長時間執行的 Lua 指令碼**

Lua 指令碼能以原子方式執行多個命令，因此完成所需的時間可能比一般 Valkey 或 Redis OSS 命令更長。如果 Lua 指令碼只執行唯獨操作，就可以讓它中途停止執行。然而，一旦 Lua 指令碼執行寫入操作，就無法讓它終止，而必須執行到完成為止。長時間執行且正在變動的 Lua 指令碼可能會導致 Valkey 或 Redis OSS 伺服器長時間沒有回應。為了解決此問題，請避免長時間執行的 Lua 指令碼，並且在生產前環境中測試指令碼。

**具有隱匿寫入的 Lua 指令碼**

有幾種方式可以讓 Lua 指令碼繼續將新資料寫入 Valkey 或 Redis OSS，即使 Valkey 或 Redis OSS 超過 `maxmemory`：
+ 指令碼會在 Valkey 或 Redis OSS 伺服器低於 時啟動`maxmemory`，並在 內包含多個寫入操作
+ 指令碼的第一個寫入命令不會耗用記憶體 (例如 DEL)，但後續更多的寫入操作則會耗用記憶體
+ 您可以在 以外的 Valkey 或 Redis OSS 伺服器上設定適當的移出政策，以緩解此問題`noeviction`。這可讓 Redis OSS 在 Lua 指令碼之間移出項目並釋放記憶體。