Skip to content

How to avoid passing KEYS into lua script when using Valkey

0

I have a lua script

local cursor = ""0""
local keys_deleted = 0

repeat
    -- scan for keys matching the pattern
    local result = redis.call(""SCAN"", cursor, ""MATCH"", @keys)
    cursor = result[1]  -- update cursor
    local keys = result[2]  -- list of keys

    -- delete the keys and count them
    for _, key in ipairs(keys) do
        redis.call(""UNLINK"", key)
        keys_deleted = keys_deleted + 1
    end
until cursor == ""0""

return keys_deleted

When running against a local docker valkey db it's okay. However when I come to run it on an AWS serverless instance of redis I get the error ERR Lua scripts without any input keys are not supported.

Is there a way to turn this off? Or fix the script. I've tried many different ways. Including passing in a dud key, passing the pattern for MATCH as the keys.

asked a year ago394 views

1 Answer
0

The error you're encountering is because Amazon ElastiCache (for both Valkey and Redis OSS) requires that Lua scripts declare their keys upfront. This is a requirement that cannot be turned off in AWS ElastiCache.

The issue with your script is that you're using the SCAN command to dynamically discover keys, but ElastiCache requires that all keys accessed by a Lua script must be provided as parameters when the script is executed.

To fix your script, you need to modify your approach. Instead of using SCAN within the script to discover keys, you should:

  1. Parameterize your script to accept the pattern as an input key
  2. Ensure all keys that will be accessed are declared upfront

Here's how you could modify your script:

-- The pattern is passed as KEYS[1]
local pattern = KEYS[1]
local cursor = "0"
local keys_deleted = 0

repeat
-- scan for keys matching the pattern
local result = redis.call("SCAN", cursor, "MATCH", pattern)
cursor = result[1]  -- update cursor
local keys = result[2]  -- list of keys

-- delete the keys and count them
for _, key in ipairs(keys) do
redis.call("UNLINK", key)
keys_deleted = keys_deleted + 1
end
until cursor == "0"

return keys_deleted

When executing this script, you would call it like:

EVAL "script_content" 1 "your:key:pattern*"

Where:

  • 1 indicates you're passing 1 key
  • "your:key:pattern*" is the pattern you want to match

This approach follows the best practice of declaring keys used in Lua scripts upfront, which is required in ElastiCache. Note that this script still uses SCAN internally, which is preferred over KEYS for production environments as it's less resource-intensive.

Remember that long-running Lua scripts can impact cluster performance, so it's advisable to test this in a pre-production environment first, especially if you're dealing with a large number of keys.
Sources
Lua scripts - Amazon ElastiCache
Overall best practices - Amazon ElastiCache

answered a year ago

EXPERT

reviewed a year ago

  • Thanks for your response. I've tried this previously. delete_keys.lua being the same script you posted.

    valkey-cli --tls -h serverless.euw2.cache.amazonaws.com -p 6379 --eval delete_keys.lua 1 "{123}:*" (error) CROSSSLOT Keys in request don't hash to the same slot

    Now these keys should be within the same slot because I put them specifically in the same slot. Using the {} syntax.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.