Lua novice tutorial: https://www.runoob.com/lua/lua-tutorial.html
Benefits of using lua scripts in Redis:
- Reduce network overhead . Multiple requests can be sent at once in the form of scripts to reduce network latency and overhead.
- Atomic operations . Redis will execute the entire script as a whole, and will not be inserted by other requests in the middle. Therefore, there is no need to worry about race conditions during script running, and there is no need to use transactions.
- Reuse . The script sent by the client will be permanently stored in redis, so that other clients can reuse the script without using code to complete the same logic.
1. Commonly used commands
EVAL
: Add the script script to the script cache and execute the script immediately- grammar:
EVAL script numkeys key [key …] arg [arg …]
- Parameter meaning:
- script : It is Lua5.1 script program. This Lua script does not need and should not define functions, it runs in the Redis server
- numkeys : The number of key parameters. That is: the number of keys in key [key ...]. If there is no key, it is 0
- key[] : Key parameter, which represents the Redis keys used in the script. These key parameters can be passed through the global variable KEYS array in Lua. Get it through KEYS[1], KEYS[2] in lua script
- arg [arg …] : Additional parameters that are not key parameters and can be accessed through the global variable ARGV array in Lua. Obtained through ARGV[1], ARGV[2] in lua script
- Case
- Call the set method:
EVAL "return redis.call('set', 'name', 'bob')" 0
- Call the set method (with parameters):
EVAL "return redis.call('set', KEYS[1], ARGV[1])" 1 name jack
- Call the set method:
- grammar:
EVALSHA
: Execute the script cached in the server based on the given SHA1 verification code. Caching scripts to the server canSCRIPT LOAD
be done with the command. Other parts of this command, such as the method of passing parameters, are theEVAL
same as the command- grammar:
EVALSHA sha1 numkeys key [key ...] arg [arg ...]
- grammar:
SCRIPT LOAD
: Add the script script to the script cache,But the script is not executed immediately.After the script is added to the cache, the scriptEVALSHA
can be called using the script'sSHA1
checksum via the command.
Scripts can remain in cache for an unlimited amount of time until SCRIPT FLUSH is executed- grammar:
SCRIPT LOAD script
. - Returns: SHA1 checksum of the script
- grammar:
SCRIPT EXISTS
: Verify whether the specified script has been saved in the cache- grammar:
SCRIPT EXISTS sha1 [sha1 ...]
- grammar:
SCRIPT FLUSH
: Clear all Lua script caches on the Redis serverSCRIPT KILL
:Used to kill the currently running Lua script. This command will take effect if and only if the script has not performed any write operations. This command is mainly used to terminate a script that takes too long to run, such as a script that loops infinitely due to a bug.
Case:
redis 127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'" # 载入一个脚本
"232fd51614574cf0867b83d384a5e898cfd24e5a"
redis 127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
1) (integer) 1
redis 127.0.0.1:6379> SCRIPT FLUSH # 清空缓存
OK
redis 127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
1) (integer) 0
2. Specific business use cases
Distributed lock based on Redis
The process of releasing the lock:
- Get the thread ID in the lock
- Determine whether it is consistent with the specified identification (current thread identification)
- If consistent, delete; otherwise, do nothing.
unlock.lua is as follows:resources/unlock.lua
-- 比较线程标示与锁中的标示是否一致
if(redis.call('get', KEYS[1]) == ARGV[1]) then
-- 释放锁 del key
return redis.call('del', KEYS[1])
end
return 0
Called in Java:
// 初始化 lua 脚本文件
private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
static {
UNLOCK_SCRIPT = new DefaultRedisScript<>();
//lua脚本位置
UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
//返回值类型
UNLOCK_SCRIPT.setResultType(Long.class);
}
// 使用 lua 脚本释放锁
public void unlock(String lockKey,String lockValue){
// 调用lua脚本
redisTemplate.execute(
UNLOCK_SCRIPT,
Collections.singletonList(lockKey),
lockValue);
}