Scripting Lua no Redis

RedisBeginner
Pratique Agora

Introdução

Neste laboratório, você explorará o Redis Lua Scripting, focando na execução de scripts Lua diretamente dentro do Redis para realizar operações complexas de forma eficiente. Este laboratório cobre o uso do comando EVAL para executar scripts, passando argumentos para scripts, carregando scripts com SCRIPT LOAD e executando scripts carregados com EVALSHA.

Começaremos executando um script Lua simples que incrementa um contador Redis usando EVAL, demonstrando como especificar o script, o número de chaves que ele acessa e os nomes das chaves. Em seguida, aprenderemos como carregar scripts no Redis e executá-los usando seu hash SHA1, melhorando o desempenho ao evitar a transmissão repetida de scripts.

Executar Script Lua com EVAL

Nesta etapa, exploraremos como executar scripts Lua diretamente dentro do Redis usando o comando EVAL. Isso permite que você execute operações complexas em seus dados em uma única solicitação, reduzindo a latência da rede e melhorando o desempenho.

Antes de começarmos, vamos entender os conceitos básicos do EVAL. O comando EVAL recebe dois argumentos principais:

  1. O próprio script Lua, como uma string.
  2. O número de chaves que o script acessará, seguido pelos nomes reais das chaves e quaisquer argumentos adicionais que você deseja passar para o script.

Aqui está um exemplo simples para você começar. Criaremos um script Lua que incrementa um contador Redis e retorna o novo valor.

  1. Abra seu terminal e conecte-se ao servidor Redis usando a interface de linha de comando do Redis (redis-cli).

    redis-cli
  2. Agora, vamos executar um script Lua usando EVAL. Este script incrementará um contador chamado mycounter e retornará o valor incrementado.

    EVAL "local current = redis.call('INCR', KEYS[1]); return current" 1 mycounter

    Vamos detalhar este comando:

    • EVAL "local current = redis.call('INCR', KEYS[1]); return current": Este é o próprio script Lua. Ele usa redis.call('INCR', KEYS[1]) para incrementar o valor da chave especificada em KEYS[1]. O array KEYS contém os nomes das chaves passadas para o script. Finalmente, ele retorna o valor incrementado.
    • 1: Isso indica que o script acessará uma chave.
    • mycounter: Este é o nome da chave que o script acessará.

    Você deve ver uma saída semelhante a esta:

    (integer) 1

    Se você executar o mesmo comando novamente, verá o contador incrementando:

    EVAL "local current = redis.call('INCR', KEYS[1]); return current" 1 mycounter

    Saída:

    (integer) 2
  3. Vamos verificar o valor da chave mycounter usando o comando GET:

    GET mycounter

    Saída:

    "2"

    Como você pode ver, o script Lua incrementou com sucesso o contador.

  4. Agora, vamos tentar outro exemplo. Desta vez, criaremos um script que define uma chave para um valor específico se ela ainda não existir.

    EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end" 1 mykey myvalue

    Neste comando:

    • EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end": Este é o script Lua. Ele verifica se a chave KEYS[1] existe. Se não existir, ele define a chave para o valor ARGV[1] e retorna 1. Caso contrário, ele retorna 0.
    • 1: Isso indica que o script acessará uma chave.
    • mykey: Este é o nome da chave.
    • myvalue: Este é o valor a ser definido se a chave não existir.

    Você deve ver uma saída semelhante a esta:

    (integer) 1

    Isso indica que a chave mykey foi definida como myvalue.

  5. Vamos verificar o valor de mykey:

    GET mykey

    Saída:

    "myvalue"

    Se você executar o comando EVAL novamente:

    EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end" 1 mykey myvalue

    Saída:

    (integer) 0

    Desta vez, o script retornou 0 porque a chave já existia.

  6. Saia do redis-cli. Isso é importante para que as alterações sejam registradas.

    exit

Passar Argumentos para o Script com EVAL

Na etapa anterior, aprendemos como executar scripts Lua com EVAL e acessar chaves. Agora, vamos explorar como passar argumentos para esses scripts. Isso permite scripts mais dinâmicos e reutilizáveis.

Lembre-se de que o comando EVAL recebe os seguintes argumentos:

  1. O próprio script Lua, como uma string.
  2. O número de chaves que o script acessará.
  3. Os nomes das chaves.
  4. Quaisquer argumentos adicionais que você deseja passar para o script. Esses argumentos são acessados dentro do script Lua usando o array ARGV.

Vamos começar com um exemplo. Criaremos um script Lua que adiciona um valor a um contador Redis. A chave do contador e o valor a ser adicionado serão passados como argumentos.

  1. Conecte-se ao servidor Redis usando a interface de linha de comando do Redis (redis-cli).

    redis-cli
  2. Agora, vamos executar um script Lua usando EVAL que incrementa um contador por uma quantidade especificada.

    EVAL "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current" 1 mycounter 5

    Vamos detalhar este comando:

    • EVAL "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current": Este é o script Lua. Ele usa redis.call('INCRBY', KEYS[1], ARGV[1]) para incrementar o valor da chave especificada em KEYS[1] pela quantidade especificada em ARGV[1].
    • 1: Isso indica que o script acessará uma chave.
    • mycounter: Este é o nome da chave que o script acessará.
    • 5: Este é o argumento que será passado para o script e acessado como ARGV[1].

    Você deve ver uma saída semelhante a esta (assumindo que mycounter estava em 2 na etapa anterior):

    (integer) 7

    O script incrementou a chave mycounter em 5.

  3. Vamos verificar o valor da chave mycounter usando o comando GET:

    GET mycounter

    Saída:

    "7"
  4. Agora, vamos tentar outro exemplo com argumentos de string. Criaremos um script que define uma chave para um valor, onde tanto a chave quanto o valor são passados como argumentos.

    EVAL "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]" 1 mynewkey mynewvalue

    Neste comando:

    • EVAL "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]": Este é o script Lua. Ele define a chave KEYS[1] para o valor ARGV[1] e retorna o valor.
    • 1: Isso indica que o script acessará uma chave.
    • mynewkey: Este é o nome da chave.
    • mynewvalue: Este é o valor a ser definido.

    Você deve ver uma saída semelhante a esta:

    "mynewvalue"
  5. Vamos verificar o valor de mynewkey:

    GET mynewkey

    Saída:

    "mynewvalue"

    O script definiu com sucesso a chave mynewkey para o valor mynewvalue.

  6. Você pode passar vários argumentos para o script. Por exemplo, vamos criar um script que concatena duas strings passadas como argumentos e define o resultado para uma chave.

    EVAL "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result" 1 combinedkey hello world

    Neste comando:

    • EVAL "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result": Este é o script Lua. Ele concatena ARGV[1] e ARGV[2] usando o operador .., define a chave KEYS[1] para o resultado e retorna o resultado.
    • 1: Isso indica que o script acessará uma chave.
    • combinedkey: Este é o nome da chave.
    • hello: Este é o primeiro argumento de string.
    • world: Este é o segundo argumento de string.

    Você deve ver uma saída semelhante a esta:

    "helloworld"
  7. Vamos verificar o valor de combinedkey:

    GET combinedkey

    Saída:

    "helloworld"
  8. Saia do redis-cli. Isso é importante para que as alterações sejam registradas.

    exit

Carregar Script com SCRIPT LOAD

Nas etapas anteriores, executamos scripts Lua diretamente usando o comando EVAL. Embora isso seja útil para scripts simples, pode se tornar complicado para scripts maiores e mais complexos. O Redis fornece o comando SCRIPT LOAD para carregar scripts no cache de scripts do servidor Redis. Isso permite que você execute o script várias vezes sem ter que enviar o script inteiro a cada vez, melhorando o desempenho.

O comando SCRIPT LOAD recebe um único argumento: o próprio script Lua. Ele retorna o hash SHA1 do script, que você pode usar para executar o script usando o comando EVALSHA (que abordaremos na próxima etapa).

Vamos ver como funciona.

  1. Conecte-se ao servidor Redis usando a interface de linha de comando do Redis (redis-cli).

    redis-cli
  2. Agora, vamos carregar um script Lua usando SCRIPT LOAD. Usaremos o mesmo script da etapa anterior que incrementa um contador por uma quantidade especificada.

    SCRIPT LOAD "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current"

    Este comando carregará o script no cache de scripts do servidor Redis e retornará o hash SHA1 do script. Você deve ver uma saída semelhante a esta:

    "6b1e8dd2999cb08546e74339c0c9489f9f89a84b"

    Este é o hash SHA1 do script. Anote este hash, pois você precisará dele na próxima etapa. O valor exato do hash pode ser diferente.

  3. Agora, vamos carregar o script que define uma chave para um valor, onde tanto a chave quanto o valor são passados como argumentos.

    SCRIPT LOAD "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]"

    Você deve ver uma saída semelhante a esta:

    "a8b2b3648969459a8198262a9166e945e890987c"

    Novamente, anote este hash.

  4. Vamos carregar o script que concatena duas strings passadas como argumentos e define o resultado para uma chave.

    SCRIPT LOAD "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result"

    Você deve ver uma saída semelhante a esta:

    "d2a800a974ca96849295220424f9a0664a495345"

    Anote este hash também.

  5. Você pode verificar se os scripts estão carregados usando o comando SCRIPT EXISTS. Este comando recebe um ou mais hashes SHA1 como argumentos e retorna um array de 0s e 1s, onde 1 indica que o script com o hash correspondente está carregado e 0 indica que não está.

    Por exemplo, para verificar se o primeiro script que carregamos ainda está carregado, use o seguinte comando, substituindo o hash pelo que você obteve na etapa 2:

    SCRIPT EXISTS 6b1e8dd2999cb08546e74339c0c9489f9f89a84b

    Saída:

    1) (integer) 1

    Isso indica que o script está carregado.

    Se você tentar verificar um script que não está carregado:

    SCRIPT EXISTS 0000000000000000000000000000000000000000

    Saída:

    1) (integer) 0

    Isso indica que o script não está carregado.

  6. Saia do redis-cli. Isso é importante para que as alterações sejam registradas.

    exit

Executar Script Carregado com EVALSHA

Na etapa anterior, aprendemos como carregar scripts Lua no cache de scripts do servidor Redis usando o comando SCRIPT LOAD. Agora, aprenderemos como executar esses scripts carregados usando o comando EVALSHA.

O comando EVALSHA recebe os seguintes argumentos:

  1. O hash SHA1 do script carregado.
  2. O número de chaves que o script acessará.
  3. Os nomes das chaves.
  4. Quaisquer argumentos adicionais que você deseja passar para o script.

Usar EVALSHA é mais eficiente do que EVAL quando você precisa executar o mesmo script várias vezes, pois evita enviar o script inteiro para o servidor a cada vez.

Vamos ver como funciona.

  1. Conecte-se ao servidor Redis usando a interface de linha de comando do Redis (redis-cli).

    redis-cli
  2. Agora, vamos executar o script Lua que incrementa um contador por uma quantidade especificada usando EVALSHA. Lembra-se do hash SHA1 que você obteve na etapa anterior para o script local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current? Caso contrário, você precisará carregar o script novamente usando SCRIPT LOAD. Para este exemplo, assumiremos que o hash é 6b1e8dd2999cb08546e74339c0c9489f9f89a84b.

    EVALSHA 6b1e8dd2999cb08546e74339c0c9489f9f89a84b 1 mycounter 5

    Vamos detalhar este comando:

    • EVALSHA 6b1e8dd2999cb08546e74339c0c9489f9f89a84b: Isso especifica que queremos executar o script com o hash SHA1 6b1e8dd2999cb08546e74339c0c9489f9f89a84b.
    • 1: Isso indica que o script acessará uma chave.
    • mycounter: Este é o nome da chave que o script acessará.
    • 5: Este é o argumento que será passado para o script e acessado como ARGV[1].

    Você deve ver uma saída semelhante a esta (assumindo que mycounter estava em 12 na etapa anterior):

    (integer) 17

    O script incrementou a chave mycounter em 5.

  3. Vamos verificar o valor da chave mycounter usando o comando GET:

    GET mycounter

    Saída:

    "17"
  4. Agora, vamos executar o script que define uma chave para um valor usando EVALSHA. Lembra-se do hash SHA1 que você obteve na etapa anterior para o script redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]? Caso contrário, você precisará carregar o script novamente usando SCRIPT LOAD. Para este exemplo, assumiremos que o hash é a8b2b3648969459a8198262a9166e945e890987c.

    EVALSHA a8b2b3648969459a8198262a9166e945e890987c 1 anotherkey anothervalue

    Você deve ver uma saída semelhante a esta:

    "anothervalue"
  5. Vamos verificar o valor de anotherkey:

    GET anotherkey

    Saída:

    "anothervalue"
  6. Se você tentar executar um script com um hash SHA1 inválido, receberá um erro:

    EVALSHA 0000000000000000000000000000000000000000 1 mykey myvalue

    Saída:

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

    Isso indica que o script com o hash SHA1 especificado não está carregado.

  7. Saia do redis-cli. Isso é importante para que as alterações sejam registradas.

    exit

Resumo

Neste laboratório, você explorou a criação de scripts Lua no Redis, com foco na execução de scripts diretamente usando o comando EVAL. Aprendemos que EVAL recebe o script Lua como uma string, o número de chaves acessadas e os próprios nomes das chaves como argumentos. Praticamos o incremento de um contador Redis usando um script Lua dentro de EVAL, observando como o script acessava e modificava a chave especificada.

Além disso, aprendemos como passar argumentos para scripts Lua, carregar scripts no Redis usando SCRIPT LOAD e executar scripts carregados usando EVALSHA. Lembre-se de sair do redis-cli após cada etapa para garantir que seus comandos sejam registrados corretamente. Isso permite uma execução mais eficiente de scripts complexos.