Redis中的Lua脚本怎么玩
Lua是一门强大、快速、轻量的嵌入式脚本语言,我们日常开发中接触的最多的还是Redis为保证原子性使用Lua执行多命令的一种方法,那么现在先来熟悉Lua基本用法。
Lua安装
Lua现在最新版本5.4.4,官网地址https://www.lua.org/
-- 解压 tar zxf lua-5.4.4.tar.gz -- 进入lua解压文件主目录 cd lua-5.4.4 -- 编译 make all test
Lua官网最新是5.4的,如果想参考中文文档可以按照5.3的版本来,中文翻译地址https://www.runoob.com/manual/lua53doc/
Lua的基本用法
Lua的基本命令都可以在Lua官方提供的测试地址进行命令测试https://www.lua.org/cgi-bin/demo
Lua申明类型
Lua中分为全局变量和局部变量,一般建议将变量定义为布局变量,效率更高
--- 全局变量 name = 'felord.cn' --- 局部变量 local age = 18
Lua数据类型
Lua中包含的数据类型有8种,string、boolean、nil、table、number、userdata、function、thread,如果仅在Redis中使用那么function、thread、userdata不建议使用,只使用其余五种就行。
这五种中,最难理解的应该是table,table和Java中提到的Hash类型有点类似,但并不是完全相同。
arr = {'zhangsan','lisi',1,true,2.1} print(arr[1]) -- table下标从1开始 print(arr[3]) print(arr[6]) print(#arr) -- 获取table的长度 ---------- 结果 zhangsan 1 nil 5
采用字典模式时,用法不一样
--- 定义字典类型 arr = {name='zhangsan',age=12,sex='男'} print(arr[1]) -- 普通取值无效 print(arr['name']) print(#arr) -- 常规获取table长度失效 ----------- 结果 nil zhangsan 0
采用混合模式时
-- 采用混合模式定义table arr = {name='zhangsan',age=12,1,sex='男',2.2} print(arr[3])-- 字典类型不会统计所以arr[]这种格式只能针对普通值 print(arr[1])--- 能够查询 print(arr[2])--- 能够查询 print(#arr)--- 只能查询普通值 print(arr['age']) print(arr['sex']) -----------结果 nil 1 2.2 2 12 男
在计算table的长度时,不能仅仅通过#arr获取,因为可能存在混合模式的情况,在不清楚元素类型的情况下建议采用循环获取table长度
Lua判断语句
-- 定义局部变量 local a = 21 if a < 10 then print('a<10') elseif a < 20 then print('20<a<=10') else print('a>=20') end
Lua循环判断
local arr = {22,23,44,name='zhangsan'} for i,v in ipairs(arr) do print('i = '..i)-- 下标 print('v = '..v)-- 值 end -- 结果 只能循环普通值,不能循环字典属性 i = 1 v = 22 i = 2 v = 23 i = 3 v = 44
通用循环可以循环字典属性
local arr = {22,23,44,name='zhangsan'} -- pairs通用循环可以循环字典属性,ipairs只能循环普通值 for i,v in pairs(arr) do print('i = '..i) print('v = '..v) end --- 结果 i = 1 v = 22 i = 2 v = 23 i = 3 v = 44 i = name v = zhangsan
Redis中Lua使用
Redis从2.6.0版本开始支持Lua脚本,在Redis中使用不需要另外安装Lua程序,Redis内嵌了Lua。
EVAL
eval定义Redis执行的命令,格式为EVAL script numkeys key [key ...] arg [arg ...]
-- 在EVAL的script中添加Lua脚本时,keys代表键值,argv代表value值是全局运行变量不能写错 -- numkeys代表键的个数,是必须的参数,不能写错 127.0.0.1:6379> EVAL "return redis.call('set',KEYS[1],ARGV[1])" 1 name zhagnsan OK 127.0.0.1:6379> keys * 1) "name" 127.0.0.1:6379> get name "zhagnsan" 127.0.0.1:6379> EVAL "return redis.call('get',KEYS[1])" 1 name "zhagnsan"
让redis执行lua脚本有两种形式,call和pcall
-- call正常返回错误信息,不做任何处理 127.0.0.1:6379> EVAL "return redis.call('no_command')" 0 (error) ERR Error running script (call to f_1e6efd00ab50dd564a9f13e5775e27b966c2141e): @user_script:1: @user_script: 1: Unknown Redis command called from Lua script -- pcall返回处理好的错误信息 127.0.0.1:6379> EVAL "return redis.pcall('no_command')" 0 (error) @user_script: 1: Unknown Redis command called from Lua script
注意点
在Redis中使用Lua时需要注意两点,Redis官方也提到这两点
精度丢失问题
在Redis中执行Lua脚本,因为是两个不同的编程环境,Lua脚本并不是区分整数和浮点数,所以Lua脚本将Lua数值转换为Redis中的值时会丢失精度,其它类型相互转换可以参考官网
-- 在将Lua中的值返回Redis 127.0.0.1:6379> EVAL "return {1,4,3.33,'zhangsan'}" 0 1) (integer) 1 2) (integer) 4 3) (integer) 3 -- 精度丢失 4) "zhangsan" -- 可以之间返回字符串,这样精度不会丢失 127.0.0.1:6379> EVAL "return {1,4,'3.33','zhangsan'}" 0 1) (integer) 1 2) (integer) 4 3) "3.33" 4) "zhangsan" -- 或者使用字符串转换函数 127.0.0.1:6379> EVAL "return {1,4,tostring(3.33),'zhangsan'}" 0 1) (integer) 1 2) (integer) 4 3) "3.33" 4) "zhangsan"
nil值处理
在前面提到Lua的8大基本数据类型就包含了nil这个类型,这个类型是Lua所特有的,无法转换到Redis中,如果在转换时遇到了nil这个值,这样将导致转换停止
127.0.0.1:6379> EVAL "return {1,4,'3.33',nil,'zhangsan'}" 0 1) (integer) 1 2) (integer) 4 3) "3.33" -- 本来后面应该还有zhangsan这个数据,但是遇到了nil转换直接停止了
Lua脚本
Lua脚本的执行都是原子性的,所以Lua脚本执行势必阻塞其它线程,那么Lua脚本不宜过大,过大会带来其它资源的消耗,也不宜将一些复杂逻辑放入Lua脚本中。
SCRIPT LOAD
Lua脚本的预加载,避免多次传输,可以重复使用
127.0.0.1:6379> SCRIPT LOAD "return 'hello lua'" "aeebf56de5e46b1d6f9e154dfdf5a1d8" -- 得到唯一字符串表示 -- 配合EVALSHA使用,和EVAL类似可以传递传参 127.0.0.1:6379> EVALSHA aeebf56de5e46b1d6f9e154dfdf5a1d8 0 "hello lua"
SCRIPT EXISTS
检查脚本是否存在
-- 存在返回1,不存在返回0 127.0.0.1:6379> SCRIPT EXISTS aeebf56de5e46b1d6f9e154dfdf5a1d8 1) (integer) 1
SCRIPT KILL
终止正在执行的脚本,如果当终止脚本执行写逻辑还未结束,这时SCRIPT KILL命令是无效的,因为这违反了Lua的原子性规则,这种情况可以使用SHUTDOWN NOSAVE命令强制结束
SCRIPT FLUSH
清空脚本缓存
SCRIPT DEBUG
如果测试bug有误还可以开启debug模式
127.0.0.1:6379> SCRIPT DEBUG yes OK 127.0.0.1:6379> SCRIPT help 2) DEBUG (YES|SYNC|NO) 3) Set the debug mode for subsequent scripts executed.
到此这篇redis的lua脚本有什么用_罗技lua脚本的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/luakf/1975.html