redis执行lua脚本

发布时间 2023-08-29 15:11:50作者: 爱编程_喵

redis执行lua脚本

简介

1. 原子操作: redis对lua脚本执行具备原子性 不需要事务维护
2. 复用高效: 客户端发送的脚本除非通过script flush清除 否则会一直被缓存 且lua由c编写而成 加载和运行速度都很快 支持不同平台可插入式编译
3. 减少网络开销: 多条指令可通过lua脚本整合一起处理 减少网络io和连接次数

常规命令

1. eval [lua脚本内容] [key数量] [key的值...] [val的值...]
	执行lua脚本
	
2. script load [lua脚本内容]
	lua脚本缓存 返回sha1值  携带sha1值执行evalsha命令才是实际执行lua
	
3. evalsha [lua缓存脚本的sha1值] [key数量] [key的值...] [val的值...]
	携带sha1值实际执行lua脚本 
	
4. script exists  [lua缓存脚本的sha1值]
	判断lua缓存脚本是否存在(0:不存在1:存在)
	
5. script flush
	删除redis服务端所有lua脚本缓存
	
6. script kill

7. redis-cli --eval [lua脚本文件位置] [key值...] , [val值...]

实例

eval

eval "redis.call('set', KEYS[1], ARGV[1]);redis.call('expire', KEYS[1], ARGV[2]);return 1;" 1 luaKey luaVal 3600

image


script load

script load  "redis.call('set', KEYS[1], ARGV[1]);redis.call('expire', KEYS[1], ARGV[2]);return 1;"

evalsha

evalsha "56574304875ec20fd85382070452bb509eeb04c0" 1 code golang 3600

image


script exists

script exists "56574304875ec20fd85382070452bb509eeb04c0"

image


script flush

script flush

image


script kill

# 模拟异常循环耗时写操作
redis> eval "while(true) do redis.call('expire', KEYS[1], ARGV[1]);end" 1 name 3600
# 模拟异常循环耗时读操作
redis> eval "while(true) do redis.call('get', KEYS[1]);end" 1 name 3600
# script kill 只作用于读操作 写操作需要停止服务才能终止异常耗时的lua脚本的执行(比如使用 shutdown nosave 终止)
redis> script kill

image


lua脚本文件执行

# 语法
redis-cli -a [密码] -h [IP地址] -p [端口号] --eval [lua脚本位置] [key值...] , [val值...]
ps: , 在key和val之间 都需要预留空格
-- 分布式锁简单示例 setnx + expire
if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then
	redis.call('expire', KEYS[1], ARGV[2]);
	return 1;
else
	return 0;
end
redis-cli --eval luaTest.lua uniqRedLock , uuid+threadId 3600

image