一、简介:
Redis从2.6版本开始引入对Lua脚本的支持,通过在服务器中嵌入Lua环境,Redis客户端可以使用Lua脚本,直接在服务端原子的执行多个Redis命令。它是由C语言实现的,虽然简单小巧但是功能强大,所以许多应用都选用它作为脚本语言
二、redis中的事务
1.概述
如果熟悉关系型数据库应该对事务比较了解,简单地说,事务表示一 组动作,要么全部执行,要么全部不执行,但是reids中的事务是
没有原子性的
只是简单的事务有异常会直接跳过并不支持回滚
2.不支持回滚的原因
(1)Redis命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
(2)因为不需要对回滚进行支持,所以 Redis的内部可以保持简单且快速。
3.保证事务原子性的两种方法:
Redis虽然不支持事务,但是提供了类似事务的两种方法如:
(1)watch命令
虽说 Redis不支持直接回滚,但我们可以通过 Redis提供的一个命令来实现回滚这个命令就是 watch,该命令可以为 Redis事务提供 check-and-set (CAS)行为。我们可以使用 watch命令来监视一个 或多个key,如果被监视的 key在事务执行前被修改过那么本次事务将会被取消,也就是所谓的回滚
注意事项:
watch要在事务开启之前就监控不然会报错
watch是一次性的
watch开启的客户端端口连接这个客户端对watch的监听就会被取消
(2)lua脚本:接下来会重点讲
三、Lua脚本的数据类型
Lua
语言提供了如下几种数据类型:
booleans
(布尔)、
numbers
(数 值)、strings
(字符串)、
tables
(表格),和许多高级语言相比,相对简单
1.字符串
local strings val = "world"
其中,local代表val是一个局部变量,如果没有local代表是全局变量。
2.数组
在
Lua
中,如果要使用类似数组的功能,可以用
tables
类型,下面代码使 用定义了一个tables
类型的变量
myArray
,但和大多数编程语言不同的是, Lua的数组下标从
1
开始计算
local tables myArray = {"redis", "jedis", true, 88.0}
3.哈希
如果要使用类似哈希的功能,同样可以使用
tables
类型,例如下面代码 定义了一个tables
,每个元素包含了
key
和
value
,其中
strings1..string2
是将两个字符串进行连接:
local tables user_1 = {age = 28, name = "tome"}
4.函数定义
在
Lua
中,函数以
function
开头,以
end
结尾,
funcName
是函数名,中间部 分是函数体
function funcName()
...
end
contact
函数将两个字符串拼接:
function contact(str1, str2)
return str1 .. str2
end
三、在Redis中使用Lua
在Redis中执行Lua脚本有两种方法:eval和evalsha。
1.eval
eval 脚本内容 key个数 key列表 参数列表
eval
命令执行
Lua
脚本过程
2.evalsha
除了使用
eval
,
Redis
还提供了
evalsha
命令来执行
Lua脚本。首先要将
Lua
脚本加载到
Redis
服务端,得到该脚本的
SHA1
校验和, evalsha命令使用
SHA1
作为参数可以直接执行对应
Lua
脚本,避免每次发送 Lua脚本的开销。这样客户端就不需要每次执行脚本内容,而脚本也会常驻 在服务端,脚本功能得到了复用
加载脚本
# redis-cli script load "$(cat lua_get.lua)"
执行脚本
evalsha 脚本SHA1值 key个数 key列表 参数列表
3.script flush
此命令用于清除Redis内存已经加载的所有Lua脚本
4.script kill
此命令用于杀掉正在执行的
Lua
脚本。如果
Lua
脚本比较耗时,甚至
Lua 脚本存在问题,那么此时Lua
脚本的执行会阻塞
Redis
,直到脚本执行完毕或 者外部进行干预将其结束
四、Lua脚本中调用redis
Lua
可以使用
redis.call
函数实现对
Redis
的访问,例如下面代码是
Lua
使用
redis.call调用了Redis的set和get操作:
redis.call("set", "hello", "world")
redis.call("get", "hello")
除此之外
Lua
还可以使用
redis.pcall
函数实现对
Redis
的调用,
redis.call
和 redis.pcall的不同在于,如果
redis.call
执行失败,那么脚本执行结束会直接返 回错误,而redis.pcall
会忽略错误继续执行脚本,所以在实际开发中要根据 具体的应用场景进行函数的选择
五、Lua脚本的优点
1.Lua
脚本在
Redis
中是原子执行的,执行过程中间不会插入其他命令。
2.Lua
脚本可以帮助开发和运维人员创造出自己定制的命令,并可以将这
些命令常驻在
Redis
内存中,实现复用的效果。
3.Lua
脚本可以将多条命令一次性打包,有效地减少网络开销