基本操作
redis中执行lua可以通过两种方式:
eval
evalsha
第一种是将lua脚本或命令直接使用redis执行,第二种相当于把脚本或命令保存到redis中,然后使用一串sha码调用(可以理解为调用函数)
eval
命令行执行
eval 脚本内容 key个数 key列表 参数列表
- 脚本内容就是要执行的lua脚本内容
- key个数表示参数中有多个个key,redis中的key是从1开始的,如果没有key的参数,就写0
- key列表,作为参数传递给Lua语言,lua中是用
KEYS[n]
来获取对应的参数 - 参数列表是传递给Lua语言,可填可不填,lua中使用
ARGV[n]
来获取对应的参数
例子(在redis中执行):
eval 'return "hello" .. KEYS[1] .. ARGV[1]' 1 redis world
输出:
"hello redisworld"
这里传入的key个数为1,所以redis是key而world是参数
执行lua脚本文件
redis-cli --eval 脚本文件 key列表,参数列表
evalsha
这个操作相当于把脚本加载到redis,得到一个SHA1的校验和,然后使用这个SHA1码来调用对于的Lua脚本,避免每次去发送Lua脚本。
加载脚本
script load
例子:
redis-cli script load "$(cat del-batch.lua)"
"e812abcb57c0360287ff97f74e444c04144382c9"
使用
执行evalsha
evalsha 脚本sha值 key个数 key列表 参数列表
如:
127.0.0.1:6379> evalsha e812abcb57c0360287ff97f74e444c04144382c9 1 A*
"del pattern is : A*, count is:0"
redis管理脚本的方式
redis提供了几个命令来管理脚本
script load
script exists
script flush
script kill
script load
用于将Lua脚本加载到redis内存中
script load [script]
script exists
用于判断sha1值是否已经加载到redis内存中
script exists sha1...
返回个数
script flush
用于清除redis内存已经加载的所有脚本
script flush
script kill
用于杀掉正在执行的Lua脚本
script kill
如果Lua脚本比较耗时,甚至Lua脚本存在问题,那么此时Lua脚本的执行会阻塞redis,直到脚本执行完毕或者外部干预将其结束
有一点需要注意,如果Lua脚本正在执行写操作,script kill
命令不会生效,这时只能等待脚本执行结束,或使用shutdown save
停掉redis服务
使用lua的优点
Lua脚本在Redis中是原子执行的,执行过程中不会插入其他命令
Lua脚本可以帮助开发和运维人员创造出自己定制的命令,并可以将这些命令存放在内存中,实现复用的效果
Lua脚本可以将多条命令一次性打包,有效减少网络开销
在lua脚本中调用redis方法
可参看redis官方文档
有两种方式可以调用
redis.call()
redis.pcall()
这两种方法都可以调用,区别是call()方法是遇到就停止执行后面的内容并直接返回错误,而pcall遇到异常会忽略掉继续执行
eval "return redis.call('set','foo','bar')" 0
OK
其他命令可参看文档这里不赘述
使用scan进行批量删除的例子
一个使用Lua脚本执行redis scan命令进行批量删除的例子,文件名为del-batch.lua
-- 定义游标cur初始值为0
local cur = 0
-- 定义删除个数初始值
local count=0
-- 循环调用
repeat
-- 调用游标
local result = redis.call("scan",cur,"match",KEYS[1])
-- 将下个游标点转化为number
cur = tonumber(result[1])
local arr = result[2]
-- 循环当前游标获取到的值,进行删除
if(arr~=nil and #arr>0) then
for i,k in pairs(arr) do
local key = tostring(k)
-- 或者使用redis.call("unlink",key)
redis.call("del",key)
count = count +1
end
end
-- 当游标点为0时,退出循环
until(cur<=0)
-- 返回执行的结果
return "del pattern is : "..KEYS[1]..", count is:"..count
调用
redis-cli --eval del-batch.lua "TEST_KEY*"
执行了之后会删除符合规则TEST_KEY*
的key
调用结果
"del pattern is : TEST_KEY*, count is:300"