Redis Lua Tutorial

Time:2022-11-24

luaredis

Introduction

Using Lua scripts in Redis is a relatively common thing in business development.Advantages of using LuaThere are the following points.

  1. For sending multiple redis commands, use Lua scripts toReduce network overhead. It is especially critical when the network transmission is slow or the response requirements are high.
    Lua scripts can process multiple requests at one time in the form of scripts, reducing network-related delays. Redis also provides Pipeline to solve this problem,
    But in the scenario where the previous instruction will affect the logic of the later instruction, Pipeline cannot satisfy.
  2. atomic operation. In the Lua script, the entire script will be executed as a whole, and the middlewill not be interrupted by other commands,thereforeGuaranteed atomicity
    Therefore, when we write Lua scripts, there is no need to consider the overall data caused by competitioninconsistent stateproblem without using transactions. And because of this property,
    It is necessary to ensure that the script does not run for too long as possible, and that the granularity of script execution is minimized.
  3. Multiplexing and packaging. for somegeneral abilityThe functions, put these into the redis script to achieve.
    other clients call the same script code, thus achieving logicalreuse
Compare Lua scripts and transactions:

The Lua script itself can also be regarded as a transaction, and it is easier to use the script, and the controllable process is more flexible.

When using Redis transactions, you will encounter twoquestion

  • Before the transaction calls EXEC, there are syntax errors (such as the number of parameters, parameter names, etc.) or server memory problems.
    When encountering this type of problem, these problems will be discovered before the server runs these instructions (after 2.6.5), and the transaction will be terminated.
  • The failure after the transaction executes the EXEC call, such as the wrong type of a certain key in the transaction. The error of the intermediate instruction will not terminate the following process,
    It also does not cause a rollback of previous instructions. In Lua scripts, however, you have full control over these.

Lua-Redis instruction tutorial

Inject and use scripts:
  1. Send the script to Redis when running the script (the network overhead is large)

    EVAL script numkeys [key ...] [arg ...]
    
    # run the script
    redis> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
    
    # Run the read-only script, the script needs to not contain any operations that modify the content. This command can be killed at will,
    # And it will not affect the stream of the copy. This command can be executed on master and replica.
    redis> EVAL_RO "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
  2. Upload the script, then use the SHA1 checksum to call the script. (Potential collision problems are generally ignored when using)

    SCRIPT LOAD script
    EVALSHA sha1 numkeys key [key ...] arg [arg ...]
    
    redis> SCRIPT LOAD "return 'hello moto'"
    "232fd51614574cf0867b83d384a5e898cfd24e5a"
    
    # run the script
    redis> EVALSHA 232fd51614574cf0867b83d384a5e898cfd24e5a 0
    "hello moto"
    
    # Run the read-only script, the script needs to not contain any operations that modify the content. This command can be killed at will,
    # And it will not affect the stream of the copy. This command can be executed on master and replica.
    redis> EVALSHA 232fd51614574cf0867b83d384a5e898cfd24e5a 0
  3. some other commands
  4. SCRIPT DEBUG is used to debug scriptsDocument
  5. SCRIPT EXISTS is used to check whether the script exists by checking the valueDocument
  6. SCRIPT FLUSH cleanup scriptDocument
  7. SCRIPT KILL stops the script currently being executed, and the default script has no write operationDocument
  8. important point
    To run the script, parameters must be passed in strict accordance with the requirements of Keys and Args.
    All operated redis keys should be placed in the Keys object, otherwise it may affect the wrong performance in the redis cluster.

    # Bad
    > eval "return redis.call('set','foo','bar')" 0
    OK
    
    # Good
    > eval "return redis.call('set',KEYS[1],'bar')" 1 foo
    OK
Call the redis command

The most commonly used in redis lua script is to call redis native instructions. There are two directives:

  1. redis.call(command, key, arg1, arg2…): When an error occurs in the call, the script is automatically terminated and the relevant Lua error is forced to be returned to the client.
  2. redis.pcall(command, key, arg1, arg2…): When an error occurs in the call, it will intercept the error and return the relevant error.

When the redis.call and redis.pcall instructions are called, the Redis Reply will be converted to the Lua type, and when the Lua script returns, the Lua type will be converted to the Redis Reply.
So these two types of conversions need to be known. You can read this document to understand the Redis protocol.Link

  • Redis integer reply: If EXISTS…
  • Redis bulk reply: such as GET…
  • Redis multi bulk reply: such as LRANGE…
  • Redis status reply: such as SET…
  • Redis error reply: Command error…
conversion table
  • Redis reply type to Lua type conversion table:

         Redis integer reply   ->   Lua number
    
            Redis bulk reply   ->   Lua string
    
      Redis multi bulk reply   ->   Lua table (may have other Redis data types nested)
    
          Redis status reply   ->   Lua table with a single ok field containing the status
    
           Redis error reply   ->   Lua table with a single err field containing the error
    
        Redis Nil bulk reply   ->   Lua false boolean type
    
    Redis Nil multi bulk reply   ->   Lua false boolean type
  • Lua type type to Redis reply conversion table:

                  Lua number   ->   Redis integer reply (the number is converted into an integer)
    
                  Lua string   ->   Redis bulk reply
    
           Lua table (array)   ->   Redis multi bulk reply (truncated to the first nil inside the Lua array if any)
    
           Lua table with      ->   Redis status reply
           a single ok field
    
           Lua table with      ->   Redis error reply
           a single err field
    
           Lua boolean false   ->   Redis Nil bulk reply.
  • Precautions
  1. Lua onlya numeric type, Lua number. There is no distinction between integers and floats, so theAlways convert Lua numbers to integer replies
    If you need floats type, please return string. (This is how the ZSCORE instruction is implemented)
  2. Thanks to LuaSemanticsReason, Lua array cannot havenils. When redis reply is converted to Lua array it willstop running
  3. whenLua TableContains keys (and its values), converted to redis reply willwill not contain keys
RESP3 – Redis 6 protocol

If you need to know, please check the official documentLink

example

the code

Reference:

  • Redis Lua combatLink
  • Redis Official DocumentationLink