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 thenprint('a<10')
elseif a < 20 thenprint('20<a<=10')
else print('a>=20')
end

Lua循环判断

local arr = {22,23,44,name='zhangsan'}for i,v in ipairs(arr) doprint('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) doprint('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'"
"aeebf56de5e46b1d6f9e154df45402368df5a1d8" -- 得到唯一字符串表示
-- 配合EVALSHA使用,和EVAL类似可以传递传参
127.0.0.1:6379> EVALSHA aeebf56de5e46b1d6f9e154df45402368df5a1d8 0
"hello lua"

SCRIPT EXISTS

检查脚本是否存在

-- 存在返回1,不存在返回0
127.0.0.1:6379> SCRIPT EXISTS aeebf56de5e46b1d6f9e154df45402368df5a1d8
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 help2) DEBUG (YES|SYNC|NO)3)     Set the debug mode for subsequent scripts executed.

Redis中的Lua脚本怎么玩相关推荐

  1. Redis中的Lua 脚本

    Lua/ˈluə/是一种轻量级脚本语言,它是用C 语言编写的,跟数据的存储过程有点类似.使用Lua 脚本来执行Redis 命令的好处: 1.一次发送多个命令,减少网络开销. 2.Redis 会将整个脚 ...

  2. 深入理解redis中的lua脚本

    本文来说下redis中的lua脚本 文章目录 概述 Lua简介 使用Lua脚本的好处 Redis+Lua实现限流 本文小结 概述 今天讲一些redis和lua脚本的相关的东西,lua这个脚本是一个好东 ...

  3. Redis中使用Lua脚本(续)- Linux下Lua-cjson开源库的安装和使用

    Redis中使用Lua脚本(续)- Lua-cjson开源库的安装和使用 问题 原因 解决方案 在Redis的lua脚本编写中,我们可能会用到json的序列化和反序列化. Json序列化: -- Re ...

  4. Redis中使用Lua脚本(二)之红包雨的抢夺

    Redis中使用Lua脚本(二)之红包雨的抢夺 一.需求介绍 二.红包雨的需求分析及概要设计 三.红包雨的Lua脚本设计及模拟演示 四.Lua脚本在生产环境的使用 一.需求介绍 如同前两年的爆款&qu ...

  5. Spring Redis中使用Lua脚本实现高并发原子操作

    1. 前言 在上一文中我对 Lua 语言的一些简单的语法及其在 Redis 中的操作进行了介绍,但是在 Java 开发中我们还需要进一步的学习才能使这种技术落地.今天就结合Spring Data Re ...

  6. redis中使用lua脚本

    一.概述 1.什么是lua脚本 Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放. 其设计目的就是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能.因为广泛的应用于:游戏开 ...

  7. Redis中的Lua脚本超时

    Redis 的指令执行本身是单线程的,这个线程还要执行客户端的Lua 脚本,如果Lua脚本执行超时或者陷入了死循环,是不是没有办法为客户端提供服务了呢? eval 'while(true) do en ...

  8. Redis中缓存Lua 脚本

    为什么要缓存 在脚本比较长的情况下,如果每次调用脚本都需要把整个脚本传给Redis 服务端,会产生比较大的网络开销.为了解决这个问题,Redis 提供了EVALSHA 命令,允许开发者通过脚本内容的S ...

  9. redis中执行lua脚本命令

最新文章

  1. 探索强化学习算法背后的思想起源!
  2. SAP MM MIRO的时候,发票价格与物料主数据的价格(移动平均价)有差异的处理
  3. ThinkSNS+ 是如何计算字符显示长度的
  4. 以云原生的名义,举办一次技术聚会
  5. android webview实例,android WebView 使用实例
  6. Ajax的get与post的区别,什么时候使用post?
  7. SpringCloud个人笔记-02-Feign初体验
  8. cvpr 深度估计_干货 | 2019 到目前为止的深度学习研究进展汇总
  9. 全国计算机等级考试题库二级C操作题100套(第24套)
  10. 为什么技术与产品沟通起来总是那么痛苦
  11. 配置SAMBA文件共享的基本方法
  12. 今天,我要教妹子学会Spring:Aware、异步编程、计划任务
  13. 转:用人单位给计算机系学生的一封信
  14. 基于PHP采集数据入库程序(二)
  15. 编译安装时的--prefix参数的使用方法,很实用,mark一下
  16. MATLAB FOR PROE
  17. 异常Throwable类
  18. MPQ Storm库 源码分析 一
  19. UML入门以及Plant UML工具介绍
  20. 2011中国民营企业500强名单,广东仅13家江浙310家

热门文章

  1. 有无孔孟之道,太阳照常升起
  2. 电脑快捷键【Crtl】
  3. Android之ScrollBar
  4. 小程序实现图片双滑放大缩小
  5. 时间序列分类算法之时间序列森林(TSF)
  6. AI写小说!ChatGPT创作福尔摩斯小说,3分钟狂写856字,就问人类慌不慌?
  7. [Erlang危机](3.0)过载处理
  8. numpy和pandas简单使用
  9. 惊心动魄修复U盘【另附U盘量产工具】(显示文件格式为RAW 需要格式化)
  10. 产学交流 | 重庆师范大学计算机学院、湖北省十堰市竹溪管委会各位专家到访芝诺数据...