Redis事务与Lua

为了保证多条命令组合的原子性, Redis提供了简单的事务功能以及集成Lua脚本来解决这个问题。

事务
事务表示一组动作, 要么全部执行, 要么全部不执行。

Redis提供了简单的事务功能, 将一组需要一起执行的命令放到multi和exec两个命令之间。 
multi命令代表事务开始, exec命令代表事务结束,它们之间的命令是原子顺序执行的。
如果要停止事务的执行, 可以使用discard命令代替exec命令即可。

如果事务中的命令出现错误, Redis的处理机制也不尽相同:

命令错误
该种类型属于语法错误, 会造成整个事务无法执行, key和value的值未发生变化。

运行时错误
如命令写错了,误把sadd写为zadd,该种类型会执行成功,且不支持回滚。需要开发人员自己进行修复

有些应用场景需要在事务之前, 确保事务中的key没有被其他客户端修改过, 才执行事务, 否则不执行(类似乐观锁) 。 Redis提供了watch命令来解决这类问题(multi命令之前执行)。


Redis提供了简单的事务, 之所以说它简单, 主要是因为它不支持事务中的回滚特性, 同时无法实现命令之间的逻辑关系计算, 当然也体现了Redis的“keep it simple”的特性。

在Redis中使用Lua
在Redis中执行Lua脚本有两种方法: eval和evalsha。
eval

用法:eval 脚本内容 key个数 key列表 参数列表
示例:
> eval 'return "hello " .. KEYS[1] .. ARGV[1]' 1 redis world
> "hello redisworld"
此时KEYS[1]="redis", ARGV[1]="world", 所以最终的返回结果是"hello redisworld"。

如果Lua脚本较长, 还可以使用redis-cli--eval直接执行文件。

eval命令执行Lua脚本过程

evalsha
除了使用eval, Redis还提供了evalsha命令来执行Lua脚本。 首先要将Lua脚本加载到Redis服务端, 得到该脚本的SHA1校验和,evalsha命令使用SHA1作为参数可以直接执行对应Lua脚本, 避免每次发送Lua脚本的开销。 这样客户端就不需要每次执行脚本内容, 而脚本也会常驻在服务端, 脚本功能得到了复用。

用法:

加载脚本: script load命令可以将脚本内容加载到Redis内存中,得到SHA1。
示例:
# redis-cli script load "$(cat lua_get.lua)"
"7413dc2440db1fea7c0a0bde841fa68eefaf149c"

执行脚本: evalsha的使用方法如下, 参数使用SHA1值, 执行逻辑和eval一致。
用法:evalsha 脚本SHA1值 key个数 key列表 参数列表
示例:
# evalsha 7413dc2440db1fea7c0a0bde841fa68eefaf149c 1 redis world
"hello redisworld"

使用evalsha执行Lua脚本过程

Lua脚本功能为Redis开发和运维人员带来如下三个好处:

·Lua脚本在Redis中是原子执行的, 执行过程中间不会插入其他命令。
·Lua脚本可以帮助开发和运维人员创造出自己定制的命令, 并可以将这些命令常驻在Redis内存中, 实现复用的效果。
·Lua脚本可以将多条命令一次性打包, 有效地减少网络开销。

Redis管理Lua脚本相关命令

script load script 此命令用于将Lua脚本加载到Redis内存中。
script exists 判断sha1是否已经加载到Redis内存中。
script flush 清除Redis内存已经加载的所有Lua脚本。
script kill 杀掉正在执行的Lua脚本。如果Lua脚本比较耗时, 甚至Lua脚本存在问题, 那么此时Lua脚本的执行会阻塞Redis, 直到脚本执行完毕或者外部进行干预将其结束。 (如果当前Lua脚本正在执行写操作, 那么script
kill将不会生效)

Redis Lua相关参数

lua-time-limit 默认5s,当Lua脚本时间超过lua-time-limit后, 向其他命令调用发送BUSY的信号, 但是并不会停止掉服务端和客户端的脚本执行, 
所以当达到lua-time-limit值之后, 其他客户端在执行正常的命令时, 将会收到“Busy Redis is busy running a script”错误, 并且提示使用script kill或者shutdown nosave命令来杀掉这个busy的脚本
原文地址:https://www.cnblogs.com/MacoLee/p/13986139.html