Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How does redis execute lua scripts

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

Editor to share with you how redis implements the lua script, I believe most people do not know much about it, so share this article for your reference, I hope you can learn a lot after reading this article, let's go to know it!

Starting with redis version 2.6.0, redis has a built-in Lua interpreter and provides eval commands to parse Lua script evaluations.

1. Grammatical format

Syntax: eval script numkeys keys args

Parameters: eval-redis provides commands for parsing lua scripts

Script-lua script

Numkeys-specifies the number of key name parameter sets (keys)

Keys-keyname parameter set, represented by an array of global variables KEYS, starting with a subscript of 1

Args-key parameter set, represented by the global variable ARGV array, with a starting subscript of 1

Description: the semantics of the EVAL command requires that the literal amount should not be written directly in the lua script. It is recommended to use variables to define the lua script, and put the literal amount in the key name parameter set keys and key parameter set args, through the global variables KEYS and ARGV to obtain, the advantage of doing so is cacheable! In the lua script, you can use two functions to execute the redis command: redis.call () and redis.pcall ()

Example:

# # first eval command, set a key=name,value=sym string eval "return redis.call ('set',KEYS [1], ARGA [1])" 1 name sym## second eval command: get the value of key=name string eval "return redis.call (' get',KEYS [1])" 1 name

Error handling:

As mentioned above, you can use call () and pcall () to execute a redis script in a lua script, and the effect of these two functions is exactly the same, except that they have different error handling:

When an error occurs when ① redis.call () executes the command, the script stops execution and returns a script error, and the error output indicates the cause of the error:

When ② redis.pcall () executes an error, it catches the error and returns the Lua table type that represents the error

two。 Type conversion

When Lua executes the Redis command through the call () or pcall () function, the return value of the command is converted to the Lua data structure; similarly, when the Lua script runs in the redis built-in interpreter, the return value of Lua is converted to Redis, and the EVAL returns the value to the client. There is an one-to-one conversion relationship between lua and redis types:

Redis-> lua

Redis Typ

Lua Typ

Description

Redis_integer

Lua_number

Convert redis integers to lua digits

Redis_bulk

Lua_string

Redis bulk reply is converted to lua string

Redis_multi bulk

Lua_table

Redis multiple bulk replies are converted to Lua table

Redis_status

Lua_table

The redis status reply is converted to a lua table, and the ok field in the table contains status information

Redis_error

Lua_table

The redis error reply is converted to the lua table, and the errfield in the table contains the error message

Redis_nil 、

Redis_multi nil

Lua_boolean_false

Redis nil reply and nil multiple reply to lua Boolean false

Lua-> redis

Lua Typ

Redis Typ

Description

Lua_number

Redis_integer

Convert lua numbers to redis integers

Lua_string

Redis_bluk

Lua string is converted to redis bulk reply

Lua_table 、

Lua_array

Redis_multi bulk

Lua table (array) converted to redis multiple bulk replies

Lua_table_ok

Redis status

A lua table with a single ok domain, converted to redis

Status reply

Lua_table_err

Redis_error

A lua table with a single ER field, converted to redis

Error reply

Lua_boolean_false

Redis nil

Lua Boolean value false to nil reply of redis

There is an additional rule for converting from lua to redis, which has no corresponding rule for converting redis to lua:

Lua_boolean_true-> redis_integer_1,lua Boolean value true is converted to redis integer 1

3.lua script 3.1 script command

Redis provides the following script commands to control the scripting subsystem:

Script flush: clear all script caches

Script load: loads the script into the script cache, does not run immediately, and returns its checksum

Script exists: checks whether the script exists in the cache according to the specified script checksum

Script kill: kill currently running scripts (prevent scripts from running caches and taking up memory)

3.2 script atomicity

Redis uses a single lua interpreter to run all scripts and ensures that the scripts are executed in an atomic way, meaning that when a script is running, no other scripts or redis commands are executed! Therefore, if the current script runs slowly, the server may not be able to execute commands because it is busy, such as:

Each script has a maximum execution time limit, and the default value is 5s. The maximum execution time is controlled by the lua-time-limit option of the profile redis.conf, or modified directly using the config get and config set commands. When a script reaches its maximum execution time, redis does not actively end it, it takes the following steps:

① redis records that a script is running out of time

② redis starts to re-accept other client requests, but only accepts script kill and shutdown nosave commands. If the client executes other commands, redis returns a busy error.

③ if the script has only performed read operations, use the script kill command to stop the script immediately; if the script has performed write operations, only the shutdown save/nosave command is allowed to prevent the current data from being written to disk by stopping the server. (at this point, the server is off and the data will not be saved)

3.3script caching and EVALSHA

Redis has an internal script caching mechanism, which does not recompile scripts every time. Instead, it keeps all run scripts permanently in the script cache (because redis finds that scripts are very small, even if they are large, and even often modified, the memory stored in these scripts is negligible). The only way to empty the script cache is to execute the script flush command. When you execute a script using the eval command, the script body is sent every time, and if the script is complex enough, it costs unnecessary network bandwidth. Redis is based on caching of lua, which implements the evalsha command.

The evalsha command has the same effect as the eval command, which interprets the execution of the lua script, but the first argument to the evalsha command is not the script body, but the script's SHAI checksum, which can be obtained through the script load command. The execution of the evalsha command is divided into two steps:

① if the redis server saves the script specified in the given SHA1 checksum, the script will be executed

② if the redis server does not save the script specified in the given SHA1 checksum, it returns a special error telling the client to use the eval command to execute

As shown in the following figure:

3.4 Global variable protection

The lua script of redis does not allow the creation of global variables. If the script needs to maintain a certain state between multiple executions, it can save the state with the help of external redis key. Before each execution of the script, the key corresponding to redis is obtained and assigned to local variables. Creating or accessing a global variable in a lua script causes the script to stop and the eval command returns an error:

Redis's global variable protection is not 100% successful, and sometimes lua global state is mixed into the script, which may lead to AOF persistence and master-slave replication can not be guaranteed. Redis does not recommend using global variables in scripts. You can use the local keyword to define variables in scripts!

3.5 logging

Using a script in redis does not automatically log, so we need to save the log information manually using redis.log () in the script. The logs saved by the script will only be recorded at the same level or higher as the log level set by the redis instance. Syntax: redis.log (loglevel,message). Where message represents the log information to be recorded, which is a string; loglevel represents the redis log level, which has four values:

Redis.LOG_DEBUG

Redis.LOG_VERBOSE

Redis.LOG_NOTICE

Redis.LOG_WARNING

The above is all the content of the article "how redis executes the lua script". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report