Todos os produtos
Search
Central de documentação

Tair (Redis® OSS-Compatible):Especificações de scripts Lua e erros comuns

Última atualização: Jun 26, 2026

As instâncias do Tair (Redis OSS-compatible) suportam comandos Lua. Use scripts Lua para lidar eficientemente com operações de comparação e definição (CAS), melhorar o desempenho da instância e implementar padrões difíceis ou ineficientes de alcançar por outros meios. Este tópico descreve a sintaxe básica e as diretrizes de uso para scripts Lua.

Sintaxe básica

Show details

Para obter mais informações sobre comandos do Redis, visite o site oficial do Redis.

Comando

Sintaxe

Descrição

EVAL

EVAL script numkeys [key [key ...]] [arg [arg ...]]

Executa um script com os parâmetros especificados e retorna o resultado.

Parâmetros:

  • script: O script Lua.

  • numkeys: Um inteiro não negativo que especifica o número de argumentos de chave no array KEYS[].

  • KEYS[]: Os argumentos de chave do Redis passados para o script.

  • ARGV[]: Os argumentos passados para o script. Os índices tanto para KEYS[] quanto para ARGV[] começam em 1.

Nota
  • Assim como o comando SCRIPT LOAD, o comando EVAL armazena o script Lua em cache na instância.

  • O uso inadequado de KEYS[] e ARGV[] pode causar comportamentos inesperados, especialmente no modo cluster. Para mais informações, consulte Restrições especiais na arquitetura cluster.

  • Recomendamos passar valores nos parâmetros KEYS[] e ARGV[] para chamar scripts Lua, em vez de codificar parâmetros diretamente nos scripts. Caso contrário, o uso de memória da máquina virtual Lua aumenta e não pode ser reduzido rapidamente. No pior cenário, ocorre um erro de falta de memória (OOM) na instância, resultando em perda de dados.

EVALSHA

EVALSHA sha1 numkeys key [key ...] arg [arg ...]

Executa um script pelo seu resumo SHA1.

Se você executar o comando EVALSHA e o script correspondente ao valor sha1 não estiver em cache no Redis, o sistema retornará um erro NOSCRIPT. Para resolver isso, use o comando EVAL ou SCRIPT LOAD para armazenar o script em cache e tente novamente. Para mais informações, consulte Erro NOSCRIPT.

SCRIPT LOAD

SCRIPT LOAD script

Armazena o script fornecido em cache na instância e retorna seu resumo SHA1.

SCRIPT EXISTS

SCRIPT EXISTS script [script ...]

Verifica se um ou mais scripts, identificados por seus resumos SHA1, existem no cache de scripts da instância. Retorna 1 para cada script existente e 0 para cada script inexistente.

SCRIPT KILL

SCRIPT KILL

Interrompe a execução de um script Lua.

SCRIPT FLUSH

SCRIPT FLUSH

Limpa todos os scripts Lua do cache de scripts da instância atual.

Os exemplos de código a seguir mostram casos de uso de comandos específicos do Redis. Antes da execução dos comandos abaixo, o comando SET foo value_test foi executado.

  • Exemplo de comando EVAL:

    EVAL "return redis.call('GET', KEYS[1])" 1 foo

    Saída de exemplo:

    "value_test"
  • Exemplo de comando SCRIPT LOAD:

    SCRIPT LOAD "return redis.call('GET', KEYS[1])"

    Saída de exemplo:

    "620cd258c2c9c88c9d10db67812ccf663d96bdc6"
  • Exemplo de comando EVALSHA:

    EVALSHA 620cd258c2c9c88c9d10db67812ccf663d96bdc6 1 foo

    Saída de exemplo:

    "value_test"
  • Exemplo de comando SCRIPT EXISTS:

    SCRIPT EXISTS 620cd258c2c9c88c9d10db67812ccf663d96bdc6 ffffffffffffffffffffffffffffffffffffffff

    Saída de exemplo:

    1) (integer) 1
    2) (integer) 0
  • Exemplo de comando SCRIPT FLUSH:

    Aviso

    Este comando exclui todos os scripts Lua em cache da instância. Faça backup dos scripts Lua antes de executar este comando.

    SCRIPT FLUSH

    Saída de exemplo:

    OK

Otimização de desempenho

Otimizar sobrecarga de memória e rede

Armazenar em cache muitos scripts funcionalmente repetitivos consome muita memória e pode até desencadear um erro de falta de memória (OOM). Veja a seguir um exemplo de uso incorreto:

EVAL "return redis.call('set', 'k1', 'v1')" 0
EVAL "return redis.call('set', 'k2', 'v2')" 0

Solução:

  • Para reduzir o desperdício de memória, evite codificar argumentos como constantes dentro do script Lua.

    # Achieves the same functionality as the incorrect example but only caches the script once.
    EVAL "return redis.call('set', KEYS[1], ARGV[1])" 1 k1 v1
    EVAL "return redis.call('set', KEYS[1], ARGV[1])" 1 k2 v2
  • Para maior eficiência, recomendamos a seguinte abordagem para reduzir tanto o uso de memória quanto a sobrecarga de rede.

    SCRIPT LOAD "return redis.call('set', KEYS[1], ARGV[1])"    # After execution, Redis returns "55b22c0d0cedf3866879ce7c854970626dcef0c3".
    EVALSHA 55b22c0d0cedf3866879ce7c854970626dcef0c3 1 k1 v1
    EVALSHA 55b22c0d0cedf3866879ce7c854970626dcef0c3 1 k2 v2

Limpar memória de scripts Lua

O cache de scripts Lua consome memória da instância, contribuindo para a métrica used_memory. Se o uso de memória da instância se aproximar ou exceder maxmemory, isso pode desencadear um erro de falta de memória (OOM). Exemplo de erro:

-OOM command not allowed when used memory > 'maxmemory'.

Solução:

Execute o comando SCRIPT FLUSH a partir de um cliente para limpar o cache de scripts Lua. O método recomendado depende da versão da sua instância:

  • Limpeza assíncrona (Recomendado): open source Redis 7.0 ou posterior e Tair (Enterprise Edition) 6.0 ou posterior suportam o comando SCRIPT FLUSH ASYNC. Este comando limpa o cache de scripts Lua em segundo plano sem bloquear a instância, minimizando o impacto nos seus serviços.

    SCRIPT FLUSH ASYNC
  • Limpeza síncrona: Para versões anteriores, o comando SCRIPT FLUSH opera de forma síncrona. Se a instância tiver muitos scripts Lua em cache, este comando pode bloqueá-la por um longo período e torná-la indisponível. Use este comando com cautela, preferencialmente fora dos horários de pico.

    SCRIPT FLUSH
Nota

Clique em Purge Data no console limpa apenas os dados e não remove o cache de scripts Lua.

Além disso, evite escrever scripts Lua excessivamente grandes para prevenir alto consumo de memória. Não realize gravações de dados em massa dentro de um script Lua, pois isso pode causar um aumento abrupto no uso de memória e levar a um erro OOM. Se sua lógica de negócio permitir, recomendamos ativar a evicção de dados (ativada por padrão com a política volatile-lru) para economizar espaço de memória. No entanto, a instância não realiza evicção do cache de scripts Lua, independentemente de a evicção de dados estar ativada.

Tratamento de erros

Erro NOSCRIPT

Ao usar o comando EVALSHA, se o script correspondente ao valor sha1 não estiver em cache na instância, ela retornará um erro NOSCRIPT. Exemplo:

(error) NOSCRIPT No matching script. Please use EVAL.

Solução:

Use o comando EVAL ou SCRIPT LOAD para armazenar o script em cache na instância e tente novamente. Contudo, a instância não garante a persistência ou replicação de scripts Lua. Em alguns cenários, como migração de instância ou alteração de configuração, o cache de scripts Lua pode ser limpo. Portanto, sua aplicação cliente deve ser capaz de lidar com esse erro. Para mais informações, consulte Problemas de persistência e replicação.

O exemplo Python a seguir mostra como lidar com um erro NOSCRIPT. Este exemplo usa um script Lua para realizar uma operação de prefixação de string.

Nota

Você também pode usar a biblioteca redis-py para Python para lidar com esse tipo de erro. A biblioteca fornece uma classe Script que encapsula a lógica de baixo nível para scripts Lua do Redis, como a captura de erros NOSCRIPT.

import redis
import hashlib

# This function takes a Lua script as a string and returns its SHA1 digest.
def calcSha1(strin):
    sha1_obj = hashlib.sha1()
    sha1_obj.update(strin.encode('utf-8'))
    sha1_val = sha1_obj.hexdigest()
    return sha1_val

class MyRedis(redis.Redis):

    def __init__(self, host="localhost", port=6379, password=None, decode_responses=False):
        redis.Redis.__init__(self, host=host, port=port, password=password, decode_responses=decode_responses)

    def prepend_inLua(self, key, value):
        script_content = """\
        local suffix = redis.call("get", KEYS[1])
        local prefix = ARGV[1]
        local new_value = prefix..suffix
        return redis.call("set", KEYS[1], new_value)
        """
        script_sha1 = calcSha1(script_content)
        if self.script_exists(script_sha1)[0]:      # Check if the script is cached in Redis.
            return self.evalsha(script_sha1, 1, key, value) # If cached, run the script with EVALSHA.
        else:
            return self.eval(script_content, 1, key, value) # Otherwise, run the script with EVAL, which also caches it. Alternatively, you could use SCRIPT LOAD and then EVALSHA.

r = MyRedis(host="r-******.redis.rds.aliyuncs.com", password="***:***", port=6379, decode_responses=True)

print(r.prepend_inLua("k", "v"))
print(r.get("k"))
            

Erros de tempo limite de script Lua

  • Como os scripts Lua são executados atomicamente, um script lento pode bloquear a instância. Se um script for executado por mais de 5 segundos, a instância retornará um erro BUSY para todos os outros comandos até que o script termine a execução.

    BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.

    Solução:

    Use o comando SCRIPT KILL para encerrar o script Lua ou aguarde sua conclusão.

    Nota
    • O comando SCRIPT KILL não surte efeito durante os primeiros 5 segundos de execução de um script lento, pois a instância está bloqueada.

    • Ao escrever scripts Lua, estime o tempo de execução e verifique problemas como loops infinitos. Isso ajuda a evitar que scripts de longa duração bloqueiem a instância e tornem o serviço indisponível. Se necessário, divida scripts longos em menores.

  • Se o script Lua atual já tiver executado um comando de escrita, o comando SCRIPT KILL não funcionará. Exemplo de erro:

    (error) UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.

    Solução:

    No console, acesse a página Instances e clique em restart para a instância correspondente.

Problemas de persistência e replicação

A instância armazena scripts Lua executados em cache indefinidamente, a menos que seja reiniciada ou que o comando SCRIPT FLUSH seja chamado. No entanto, em certas situações, como migração de instância, alteração de configuração, atualização de versão ou failover de HA, a instância não garante a persistência de scripts Lua nem sua replicação para outros nós.

Solução:

Como a instância não garante a persistência ou replicação de scripts, armazene todos os scripts Lua localmente. Quando necessário, use o comando EVAL ou SCRIPT LOAD para recolocar os scripts em cache na instância. Isso evita erros NOSCRIPT que podem ocorrer se o cache de scripts for limpo durante operações como reinicialização de instância ou failover de HA.

Restrições especiais na arquitetura cluster

Restrições da arquitetura cluster

  • Para garantir atomicidade, um script Lua não pode ser dividido e deve ser executado em um único shard na arquitetura cluster. A instância geralmente usa uma chave para determinar para qual shard rotear o comando. Portanto, especifique pelo menos uma chave ao executar um script Lua em um cluster. Se um script acessar várias chaves, todas devem pertencer ao mesmo slot; caso contrário, o script falhará ou retornará resultados incorretos. Comandos sem chaves, como KEYS, SCAN e FLUSHDB, podem ser executados, mas retornarão dados apenas de um único shard. Essas limitações são inerentes à arquitetura Redis Cluster.

  • Executar o comando SCRIPT LOAD em um único nó não garante que o script esteja armazenado em outros nós.

Códigos de erro no modo proxy

O proxy realiza verificações de sintaxe para identificar proativamente casos em que chaves abrangem vários slots. Isso ajuda a detectar problemas precocemente, facilitando a solução de problemas. O método de verificação do proxy difere do da máquina virtual Lua, resultando em restrições adicionais ao executar comandos Lua no modo proxy. Por exemplo, o comando UNPACK não é suportado, e EVAL, EVALSHA e comandos da série SCRIPT não podem ser usados dentro de transações MULTI/EXEC.

Desative algumas verificações de sintaxe Lua do proxy desligando o parâmetro script_check_enable.

Adicionalmente, para uma instância de divisão de leitura/escrita, se o parâmetro readonly_lua_route_ronode_enable estiver habilitado, o proxy verifica se um script Lua contém apenas comandos de leitura para determinar se pode ser encaminhado para um nó somente leitura. Essa lógica de verificação impõe limitações à sintaxe Lua.

Nota

Desativar o parâmetro script_check_enable tem os seguintes efeitos:

  • Para instâncias de open source Redis 5.0 (versões secundárias anteriores a 5.0.8) ou Redis 4.0 e anteriores, não recomendamos desativar este parâmetro. Fazer isso pode fazer com que um script retorne uma mensagem de sucesso mesmo quando executado incorretamente.

  • Para outras versões, desativar este parâmetro faz com que o proxy pare de verificar a sintaxe Lua, mas os nós de dados ainda realizarão suas verificações normais de sintaxe.

A seguir estão os códigos de erro específicos e suas causas.

Limitações da arquitetura Redis Cluster

  • Código de erro: -ERR for redis cluster, eval/evalsha number of keys can't be negative or zero\r\n

    Descrição: Especifique pelo menos uma chave ao executar um script Lua. O proxy usa a chave para determinar para qual shard encaminhar o script.

    # Correct example
    EVAL "return redis.call('get', KEYS[1])" 1 fooeval
    
    # Incorrect example
    EVAL "return redis.call('get', 'foo')" 0
  • Código de erro: -ERR 'xxx' command keys must in same slot

    Descrição: Todas as chaves em um script Lua devem pertencer ao mesmo slot.

    # Correct example:
    EVAL "return redis.call('mget', KEYS[1], KEYS[2])" 2 foo {foo}bar
    
    # Incorrect example:
    EVAL "return redis.call('mget', KEYS[1], KEYS[2])" 2 foo foobar

Restrições de sintaxe Lua do proxy

Nota

Evite as verificações adicionais de sintaxe Lua do proxy desativando o parâmetro script_check_enable.

  • Código de erro: -ERR bad lua script for redis cluster, nested redis.call/redis.pcall

    Descrição: Chamadas aninhadas ao Redis não são suportadas. Use variáveis locais como alternativa.

    # Correct example
    EVAL "local value = redis.call('GET', KEYS[1]); redis.call('SET', KEYS[2], value)" 2 foo bar
    
    # Incorrect example
    EVAL "redis.call('SET', KEYS[1], redis.call('GET', KEYS[2]))" 2 foo bar
  • Código de erro: -ERR bad lua script for redis cluster, first parameter of redis.call/redis.pcall must be a single literal string

    Descrição: O comando invocado dentro de redis.call/pcall deve ser uma string literal.

    # Correct example
    eval "redis.call('GET', KEYS[1])" 1 foo
    
    # Incorrect example
    eval "local cmd = 'GET'; redis.call(cmd, KEYS[1])" 1 foo

Restrictions in specific versions (applies only to open source Redis 5.0 with minor versions earlier than 5.0.8, Redis 4.0 and earlier, cloud-native edition with proxy versions earlier than 7.0.2, and classic edition with proxy versions earlier than 6.8.12)

Nota
  • As restrições a seguir aplicam-se apenas a open source Redis 5.0 (versões secundárias anteriores a 5.0.8), Redis 4.0 e anteriores, ou instâncias com versões de proxy mais antigas (cloud-native edition anterior a 7.0.2 ou classic edition anterior a 6.8.12).

  • Geralmente, se as versões da sua instância e do proxy forem superiores às listadas, ignore o conteúdo a seguir. No entanto, se sua instância for de uma versão superior mas ainda apresentar essas restrições, modifique qualquer parâmetro do proxy (como query_cache_expire), aguarde 1 minuto e tente novamente.

  • Código de erro: -ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array\r\n

    Descrição: Todas as chaves devem ser passadas através do array KEYS. Para comandos dentro de redis.call/pcall, as posições das chaves devem usar o array KEYS, e não é possível substituir KEYS por uma variável Lua.

    # Correct example:
    EVAL "return redis.call('mget', KEYS[1], KEYS[2])" 2 foo {foo}bar
    
    # Incorrect examples:
    EVAL "return redis.call('mget', KEYS[1], '{foo}bar')" 1 foo                      # The key '{foo}bar' should be passed through the KEYS array.
    EVAL "local i = 2 return redis.call('mget', KEYS[1], KEYS[i])" 2 foo {foo}bar    # This script is not allowed in proxy mode because the KEYS array index is a variable. This restriction does not exist in direct connection mode.
    EVAL "return redis.call('mget', KEYS[1], ARGV[1])" 1 foo {foo}bar                # An element from the ARGV array should not be used as a key.
  • Código de erro: -ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array, include destination, and KEYS should not be in expression

    Descrição: O parâmetro destination dos comandos ZUNIONSTORE e ZINTERSTORE deve ser passado usando o array KEYS.

  • Código de erro: -ERR bad lua script for redis cluster, ZUNIONSTORE/ZINTERSTORE numkeys parameter should be a single number and not expression

    Descrição: O parâmetro numkeys dos comandos ZUNIONSTORE e ZINTERSTORE deve ser uma constante, não uma expressão.

  • Código de erro: -ERR bad lua script for redis cluster, ZUNIONSTORE/ZINTERSTORE numkeys value is not an integer or out of range

    Descrição: O parâmetro numkeys dos comandos ZUNIONSTORE e ZINTERSTORE não é um número.

  • Código de erro: -ERR bad lua script for redis cluster, ZUNIONSTORE/ZINTERSTORE all the keys that the script uses should be passed using the KEYS array

    Descrição: Todas as chaves para os comandos ZUNIONSTORE e ZINTERSTORE devem ser passadas usando o array KEYS.

  • Código de erro: -ERR bad lua script for redis cluster, XREAD/XREADGROUP all the keys that the script uses should be passed using the KEYS array

    Descrição: Todas as chaves para os comandos XREAD e XREADGROUP devem ser passadas usando o array KEYS.

  • Código de erro: -ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array, and KEYS should not be in expression, sort command store key does not meet the requirements

    Descrição: A chave para o comando SORT deve ser passada usando o array KEYS.

Problemas de permissão de leitura/escrita

  • Código de erro: -ERR Write commands are not allowed from read-only scripts

    Descrição: Scripts Lua enviados com o comando EVAL_RO não podem conter comandos de escrita.

  • Código de erro: -ERR bad write command in no write privilege

    Descrição: Scripts Lua enviados de uma conta somente leitura não podem conter comandos de escrita.

Comandos não suportados

  • Código de erro: -ERR script debug not support

    Descrição: Atualmente, o proxy não suporta o comando SCRIPT DEBUG.

  • Código de erro: -ERR bad lua script for redis cluster, redis.call/pcall unkown redis command xxx

    Descrição: O script Lua contém um comando que não é suportado pelo proxy. Para mais informações, consulte Restrições de comandos em instâncias cluster e de divisão de leitura/escrita.

Erros de sintaxe Lua

  • Código de erro: -ERR bad lua script for redis cluster, redis.call/pcall expect '(' ou -ERR bad lua script for redis cluster, redis.call/redis.pcall definition is not complete, expect ')'

    Nota: Trata-se de um erro de sintaxe Lua, pois a função redis.call deve ser seguida por um par completo de parênteses: ( e ).

  • Código de erro: -ERR bad lua script for redis cluster, at least 1 input key is needed for ZUNIONSTORE/ZINTERSTORE

    Descrição: O parâmetro numkeys dos comandos ZUNIONSTORE e ZINTERSTORE deve ser maior que 0.

  • Código de erro: -ERR bad lua script for redis cluster, ZUNIONSTORE/ZINTERSTORE key count < numkeys

    Descrição: O número real de chaves para o comando ZUNIONSTORE ou ZINTERSTORE é menor que o valor numkeys especificado.

  • Código de erro: -ERR bad lua script for redis cluster, xread/xreadgroup command syntax error

    Descrição: A sintaxe do comando XREAD ou XREADGROUP está incorreta. Verifique o número de parâmetros.

  • Código de erro: -ERR bad lua script for redis cluster, xread/xreadgroup command syntax error, streams must be specified

    Descrição: Os comandos XREAD e XREADGROUP devem incluir o parâmetro streams.

  • Código de erro: -ERR bad lua script for redis cluster, sort command syntax error

    Descrição: A sintaxe do comando SORT está incorreta.

Perguntas frequentes

  • P: Posso executar scripts Lua no Data Management (DMS)?

    R: O console do Data Management (DMS) atualmente não suporta comandos relacionados a Lua. Para usar scripts Lua, conecte-se à sua instância usando um cliente ou redis-cli.