Introduction to Lua

Lua is a lightweight scripting language written in standard C and open as source code. It is designed to be embedded in applications to provide flexible extension and customization capabilities.

Language features

The Lua language has the following features:

  • Lightweight it is written in standard C language and open in the form of source code, compiled only more than one hundred K, can be very convenient embedded in other programs.
  • Extensible Lua provides very easy to use extension interfaces and mechanisms: the host language (usually C or C++) provides these functions, and Lua can use them as if they were already built in.
  • Other features support procedure-oriented and functional programming;

Automatic memory management; Only provides a general type of table (table), with it can achieve array, hash table, collection, object; Language built-in pattern matching; Closure (closure); A function can also be viewed as a value; Multithreading (collaborative processes, not threads supported by the operating system) support; Closures and tables make it easy to support some of the key mechanisms needed for object-oriented programming, such as data abstraction, virtual functions, inheritance, and overloading.

Application scenarios

Lua is used in the following scenarios:

  • The game development
  • Standalone application scripts
  • Web Application Scripts
  • Extensions and database plug-ins such as MySQL Proxy and MySQL WorkBench
  • Security systems, such as intrusion detection systems
  • Redis

The data structure

struct redisServer {
	// Ignore other configuration information
	
    / / the Lua environment
    lua_State *lua; /* The Lua interpreter. We use just one for all clients */
    
    // Copy the fake client that executes the Redis command in Lua script
    redisClient *lua_client;   /* The "fake client" to query Redis from Lua */

    // The client that is currently executing EVAL, or NULL if not
    redisClient *lua_caller;   /* The client running EVAL right now, or NULL */

    // a dictionary with values for Lua scripts and keys for SHA1 checksums of scripts
    dict *lua_scripts;         /* A dictionary of SHA1 -> Lua scripts */
    // The execution time of Lua scripts
    mstime_t lua_time_limit;  /* Script timeout in milliseconds */
    // The time when the script starts executing
    mstime_t lua_time_start;  /* Start time of script, milliseconds time */

    // Whether the script executed a write command
    int lua_write_dirty;  /* True if a write command was called during the execution of the current script. */

    // Does the script execute random commands
    int lua_random_dirty; /* True if a random command was called during the execution of the current script. */

    // Whether the script times out
    int lua_timedout;     /* True if we reached the time limit for script execution. */

    // Whether to kill the script
    int lua_kill;         /* Kill the script if true. */
};
Copy the code

Above, the data representation of Lua in Redis is stored in the Redis server of redisServer

  • Lua represents the lua execution environment. All clients share a Lua execution environment
  • lua_clientCopy to performLuaPseudo client of the Redis command in the script
  • lua_callerCurrently executingEVALCommand client, if not NULL
  • lua_scriptsUsed hereThe dictionaryStore, key for scriptSHA1Checksum, the value of Lua script, i.e<SHA1,SCRIPT>.

Collaboration component

The pseudo client

In Redis, there is only one Lua execution environment for all clients. This Lua execution environment is specialized in handling Lua scripting related functions, which reflects a better execution environmentIsolation,andindependence, and it is as a host language of Redis, Redis as the host of Lua, so in the use of Lua’s various language features and advantages at the same time, but also compatible with the host Redis language command support, in order to avoid coupling, Redis here uses aThe pseudo clientTo connect Redis and Lua, so that Lua scripts can easily call command support provided by Redis.Lua script can passredis.callorredis.pcallThe Redis function calls the Redis command as follows:

  • Lua environmentwillredis.callorredis.pcallFunction to execute the command toThe pseudo client
  • The pseudo-client passes the execution command to Redis’s command executor
  • The command executor executes the command and returns the execution result to the pseudo client
  • The pseudo client receives the returned results and returns them to the Lua environment
  • The return result is initiated from the callredis.callorredis.pcallFunction to return to the caller

The script cache

Lua script cache will be used asThe dictionaryThe Key is a script fileSHA1 check andThe Value for ValueThe script file, that is, script content.

Because Lua scripts may be large and batch commands for Redis commands, in order to reduce the performance loss incurred by script execution on network transmission, Lua scripts are cached and file checksums are used to match cached script data to improve performance

Command implementation

eval

As mentioned above, Lua script execution is divided into three main steps

  • (1) Define script functions
    • ① Calculation scriptSHA1File checksum
    • (2) tof_SHA1The format constructs the script function, whose body content is the script itself, as in
f_1as8dsdsjz8sww9(){
	return 1 + 2;
}
Copy the code

The advantages of using a function body to hold scripts are:

  • It is easy to call and can be located through the function SHA1
  • You can take advantage of the local nature of the functions to keep the Lua environment clean, reduce garbage collection, and avoid global variables
  • Script utilization can be improved because if a script function has been defined, then subsequent function execution only requires SHA1 calls, eliminating repetitive processing
  • (2) Cache script functions
    • (3) inlua_scriptsIn the dictionary<SHA1,SCRIPT>Mapping relational storage
  • (3) Execute script functions
    • (4) The script parameters are loaded before executing the script function
    • ⑤ Set the script execution timeout hook, can be executed in thescript skillorshutdownStopping script execution
    • ⑥ Executing scripts
    • ⑦ Remove the script execution timeout hook
    • 8 Save the script execution result to the client buffer
    • ⑨ Lua environment garbage collection

evalsha

  • Compute the SHA1 checksum of the script
  • Concatenate SHA1 method functions
  • Verify the existence of functions

script flush

Clear the scripts cached in the lua_scripts dictionary and reset the Lua environment

script load

Load the script into the lua_scripts dictionary

script exists

Verify that the script exists in the lua_scripts dictionary

script kill

Stop the currently executing script through the script hook

Lua differs from Redis

Lua is a collection of Redis commands. Since it runs in a separate Lua environment, Lua script content is executed atomically. Therefore, it runs in a single-threaded environment, which is different from Redis native commands when a client executes a series of commandsJump the queue.

Lua scripting advantages

  • Lua scripts are executed atomically in Redis and no other commands are inserted during execution.
  • Lua scripts help developers and operations create their own custom commands that can reside in Redis memory for reuse.
  • Lua scripts can package multiple commands at once, effectively reducing network overhead

conclusion

  • Lua scripts have good atomicity due to the natural isolation of execution environment, which can encapsulate batch commands and complex logic during execution. This is a great complement to Redis transaction mechanism, and provides a way to use atomic operations for batch execution
  • Because Lua communicates with Redis in the form of pseudo client transfer, the execution performance is worse than Redis native execution command in theory, so it needs to make a choice according to the actual situation in actual use

reference

Redis Design and Implementation

www.runoob.com/lua/lua-tut…