Redis——“事务“/Lua脚本

1.redis的事务

Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务(transaction)功能。

eg:

事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求。

在传统的关系式数据库中,常常用 ACID 性质来检验事务功能的可靠性和安全性。而redis中的事务不是原子性的(伪事务),一条失败,其余的会执行下去;

执行失败的原因有这些:

1.命令错误:比如说语法错误, set写成了sett,整个的事务将无法执行;

2.运行时错误:语法正确,例如参数错误,expire命令的第二个参数为时间,应该是Integer类型,结果写成了String类型;

3.业务逻辑错误:比如说应该用sadd,却误写成了zadd,从语法上讲,是没有毛病的,但是上面的写对的命令,已经执行入库了, 这种情况就需要开发人员自己修复了;

既然redis中的事务不是原子性的,那么如果要实现对redis的多命令事务操作,可以使用lua脚本;

2. LUA脚本

lua脚本命令的语法如下:

EVAL script numkeys key [key ...] arg [arg ...]

说明:

EVAL 为命令的前缀,固定写法;

script  为脚本语句,一段字符串,如"return xx,redis.call(xx);"

numkeys 指定后续参数有几个key;

key [key ...],是要操作的键,可以指定多个,在lua脚本中通过KEYS[1], KEYS[2]获取;

arg [arg ...],参数,在lua脚本中通过ARGV[1], ARGV[2]获取。

示例:

1. 将脚本直接写在命令中;

启动redis,打开redis-cli.exe

 2. 通过.lua文件执行脚本

3. 工程中使用Lua脚本的示例

(1)lua脚本内容

 (2)导入.lua文件

(3)代码中通过RedisClusterTemplete执行脚本

(4)调用的底层源码: 

4. Lua脚本与multi命令的比较

Lua脚本与multi命令在执行过程中,遇到异常时的处理是不同的,这里附上几个关于multi命令与lua脚本的执行错误的情况下的结果测试:

测试(1)——存在语法错误

 发现问题,这里是在multi命令里面有语句错误,执行exec命令时会报错,导致错误语句的前后的其他正确的语句没有执行

测试(2)——语法正确 执行时的参数转换错误

 语句未出错,而是由于方法的调用出错(例如参数类型错误,应该传入Integer而非String,而非语句错误),后续的命令依旧会执行

测试(3)——Lua脚本中命令语法出错:(lua脚本)

再看看如果是语句本身出错了呢,即命令错误:

lua脚本如下:3个key,3个参数argv,分别set、分配ttl、set

执行lua脚本:

 来看看执行结果:

 测试(4)——Lua脚本执行时参数出错:(lua脚本)

lua脚本如下:3个key,3个参数argv,分别set、分配ttl、set

 执行脚本:此时redis没有key为空,先让参数ARGV[2]为非Integer的值(参数错误)

 此时来看看其他的语句的执行情况,看看后面的key3设置成功没有:

 结果与测试(3)一样;

说明:lua脚本与multi命令(事务)是不一样的,如果发生错误(无论是语法还是参数错误),前面正确的语句可以被执行,而出现错误语句的后面的语句不会执行!

lua脚本的好处:

1.lua脚本是作为一个整体执行的.所以中间不会被其他命令插入;

2.可以把多条命令一次性打包,所以可以有效减少网络开销;

3.lua脚本可以常驻在redis内存中,所以在使用的时候,可以直接拿来复用.也减少了代码量.

小结:

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

对于multi命令的事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

对于lua脚本,如果在某一句执行失败,后面的指令是不会执行的。

5. 代码附录

参考:编码技巧——Lua脚本如何在项目中使用

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值