一。概述
LUA脚本语言是C开发的,类似存储过程
是一个小巧的脚本语言,由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译,运行。
一个完整的Lua解释器不过200k,在目前所有脚本引擎中,Lua的速度是最快的。
Lua语言里的操作提供原子性
使用LUA脚本的好处
减少网络开销,在Lua脚本中可以把多个命令放在同一个脚本中运行
原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无需担心会出现竞态条件
复用性,客户端发送的脚本会永远存储在redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑
二。LUA编译器安装
下载地址:wget http://www.lua.org/ftp/lua-5.3.5.tar.gz
解压:tar -zxvf lua-5.3.5.tar.gz
输入:lua显示版本并进入控制台
三。数据类型、基本语法以及示例
数据类型:
Lua中有8个基本类型分别为:nil、boolean、number、string、userdata、function、thread和table。
nil 这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean 包含两个值:false和true。
number 表示双精度类型的实浮点数
string 字符串由一对双引号或单引号来表示
function 由 C 或 Lua 编写的函数
userdata 表示任意存储在变量中的C数据结构
thread 表示执行的独立线路,用于执行协同程序
table 相当于数组 Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字或者是字符串。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。
关键字:
and break do if then else elseif end false for function in
local nil not or repeat return true until while
单行注释 --
多行注释 --[[ --]]
打印 print(“hello world”)
KEYS[1] 第一个key eval "" 2 param1 param2 param3 param4 //2个key分别为param1 param2 两个参数分别为param3 param4
ARGV[1] 第一个value值
local count = redis.call('get',KEYS[1] )
redis.call('get',KEYS[1]
redis.call('set',KEYS[1], count-ARGV[1])
五。lua脚本的执行
方法1:客户端eval(redis客户端直接写脚本)
步骤1.先进入客户端:src/redis-cli -h 192.168.61.139 -p 6379 -a 123456 (或者src/redis-cli redis.conf)
步骤2.运行 eval script numkeys key [key ...] arg [arg ...]
eval "return ARGV[1]" 0 100 //0个key 一个参数100
eval "" 0 100 101 //0个key 两个参数分别为100 101
eval "" 2 param1 param2 param3 param4 //2个key分别为param1 param2 两个参数分别为param3 param4
上面绿色部分就是lua脚本语句
return ARGV[1] 返回第一个参数
return {KEYS[1],ARGV[1]} 返回第一个key和第一个参数
方法2:客户端evalsha(单独一个脚本文件)
步骤1:编写脚本文件 test.lua
步骤3:加载脚本文件,得到sha1值
./redis-cli -h 192.168.61.139 -p 6379 -a 123456 script load "${cat test.lua}"
步骤3:进入客户端:./redis-cli -h 192.168.61.139 -p 6379 -a 123456
步骤4:运行脚本: evalsha sha1值 2 param1 param2 param3 param4
方法3:java代码(pom引入jedis依赖)
jedis.set("product_stock_10016", "15"); //设置一个key
String script = " local count = redis.call('get',KEYS[1] ) " + //获取key 的值
" redis.call('set',KEYS[1], count-ARGV[1]) "; //设置key的值
Object luaResult = jedis.eval(script, Arrays.asList("product_stock_10016"), Arrays.asList("10"));
System.out.println(luaResult);
六。客户端脚本管理命令(单独一个脚本文件)
七。redis+lua的使用场景:限流,抢红包,分布式锁
1.redis+lua实现限流
2.redis+lua实现抢红包
3.redis+lua实现分布式锁