lua-redis

Introduction to the

Using Lua scripts in Redis is a fairly common practice in business development, and there are several advantages to using Lua.

  1. For sending with multiple REDIS instructions, use Lua scriptsReduce network overhead. This is especially critical when the network is slow or the response is high.

    Lua scripts can handle multiple requests at once in a scripted manner, reducing latency associated with the network. Redis also provided PIPELINE to address this problem,

    However, in cases where previous instructions affect the logic of subsequent instructions, a Pipeline does not suffice.
  2. Atomic operation. In a Lua script, the entire script is executed as a whole, in the middleIt will not be interrupted by other commands, soIt's atomic.

    So when we write a Lua script, we don’t need to think about the overall data caused by the competitionState inconsistencyWithout the use of transactions. And because of this feature,

    Make sure that the script doesn’t take as long to run as possible and that the granularity of the script execution is minimal.
  3. Reuse and encapsulation. Aimed at someGeneral ability“, put these into the Redis script to implement.

    Other clients call the same script code, thus reaching the logicalreuse.

Contrast Lua scripts with transactions:

A Lua script can also be viewed as a transaction in itself, and it is simpler to use a script and more flexible to control the flow.

There are two kinds of problems when using Redis transactions:

  • Transaction generates syntax error (number of parameters, parameter name, etc.) or server memory problem before calling EXEC. In this case, the problem will be detected before the server runs the instructions (after 2.6.5) and the transaction will be aborted.
  • Failure of a transaction after an EXEC call has been made, such as a problem with the wrong type of a key in the transaction. An error in an intermediate instruction does not terminate the subsequent flow or cause a rollback of the previous instruction. In a Lua script, however, you have complete control over this.

Lua-Redis instruction tutorial

Injecting and using scripts:

  1. Send the script to Redis while running it (high network overhead)

    EVAL script numkeys [key ...]  [arg ...] Return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second # This directive can be killed at will, # and 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, and then invoke the script using a SHA1 checksum. (Potential collision issues, generally ignored when using)

    SCRIPT LOAD script EVALSHA sha1 numkeys key [key ...]  arg [arg ...] Redis > SCRIPT LOAD "return" hello moto '", "232 fd51614574cf0867b83d384a5e898cfd24e5a" # redis running SCRIPT > EVALSHA # 232 fd51614574cf0867b83d384a5e898cfd24e5a 0 "hello moto" run only read the script, the script need does not contain any modify the content of operation. This directive can be killed at will, # and will not affect the stream of the copy. This command can be executed on master and replica. redis> EVALSHA 232fd51614574cf0867b83d384a5e898cfd24e5a 0
  3. Some other instructions
  4. Script Debug is used to DEBUG the Document SCRIPT
  5. Script EXISTS checks the existence of a Document in the SCRIPT through a checkvalue
  6. SCRIPT FLUSH FLUSH SCRIPT Document
  7. The default SCRIPT does not write the operation Document
  8. Note that the script needs to strictly follow the Keys and Args to pass the parameters. All Redis Keys accessed should be placed in the Keys object, otherwise it may affect the incorrect 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

Invoke the Redis directive

The most common way to use Redis Lua scripts is to call Redis native directives. There are two directives:

  1. redis.call(command, key, arg1, arg2…) : Automatically terminates the script when an error occurs in the call, forcing the relevant Lua error back to the client.
  2. redis.pcall(command, key, arg1, arg2…) : When an error occurs in a call, an error intercept is performed and the associated error is returned.

The Redis Reply will be converted to the Lua type when the Redis. call and Redis. pcall directives are invoked, and the Lua type will be converted to the Redis Reply when the Lua script returns. So these two types of conversions need to be known. You can read this documentation for the Redis protocol. Link

  • Redis Integer Reply: As EXISTS…
  • Redis Bulk Reply: e.g. GET…
  • Redis Multi Bulk Reply: such as Lrange…
  • Redis Status Reply: Set…
  • Redis Error Reply: Error…
Translation table
  • Redis 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.
  • Matters needing attention
  1. Lua onlyA numeric typeThe Lua number. Integers and floats are not distinguished, so you willAlways convert Lua Numbers to Integer replies.

    If you need a float type, return a string. (This is how the ZScore directive is implemented.)
  2. Due to the LuaThe semanticLua Array can not havenils. When the Redis reply is converted to the Lua ArrayTermination of the operation.
  3. whenLua TableConvert the keys(and their values) into the REDIS ReplyIt doesn't include keys.
Resp3-Redis 6 agreement

See the official documentation Link for more information

The sample

code

Reference:

  • Redis Lua Combat Link
  • Redis official documentation Link