https://juejin.cn/post/6891158857708797959
首先Redis事务在实际的场景应用上也占着比较重要的地位,例如在秒杀场景中,我们就可以利用Redis事务中的watch命令监听key,实现乐观锁,保证不会出现冲突,也防止商品超卖。
另外就是Redis事务也是面试过程中面试官着重照顾的基础知识对象,假设面试官问你实现Redis事务有哪些方式?事务发生错误时Redis是怎么处理的?Redis事务支持回滚吗等等这些问题,你是否能脱口而出回答上来呢?如果你对这方便的基础知识有所欠缺,那是不是就栽跟头了呢?
两种实现方式
redis命令 MULTI、EXEC、DISCARD、WATCH
multi开启事务
exec是执行
disccard是放弃事务返回
重点讲下watch
WATCH 命令用于在事务开始之前监视任意数量的键,当调用 EXEC 命令执行事务时, 如果任意一个被监视的键已经被其他客户端修改了, 那么整个事务不再执行, 直接返回失败。
看例子:
- 首先我们在一个Redis客户端一上使用 WATCH 命令监控两个key,分别为name和sex,然后开启事务,在事务中修改name的值,
- 在客户端一执行 EXEC 命令之前,我们另外开一个客户端二,在客户端二中我们修改sex的值为man
接着我们回到客户端一执行 EXEC 命令
# 客户端一
127.0.0.1:6379> get name
"dashu"
127.0.0.1:6379> get sex
"male"
127.0.0.1:6379> WATCH name sex
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set name saycode
QUEUED
127.0.0.1:6379> EXEC
(nil) # 事务失败
127.0.0.1:6379> get sex
"man"
127.0.0.1:6379> get name
"dashu"#--------- 这是一条分割线 ---------## 客户端二
127.0.0.1:6379> get sex
"male"
127.0.0.1:6379> set sex man
OK
从上面执行的结果可以看到,客户端一中的事务失败了,事务中所修改的name的值也不成功。主要原因是:调用 EXEC 命令执行事务时,被监控的sex 被客户端二修改了,所以客户端一的事务不再执行
watch命令的原理 看 https://juejin.cn/post/6891158857708797959
Lua脚本
除了上面介绍的命令模式可以实现Redis事务外,其实还有一种非常重要的方式:Lua脚本。
为什么要夸Lua脚本呢?我们来看看Lua脚本有什么优势:
原子操作:Redis确保脚本执行期间,其它任何脚本或者命令都无法执行。也就是说,在编写脚本的过程中无需担心会出现竞态条件,无需使用事务。
减少网络开销:可以将多个请求通过脚本的形式一次发送,减少网络时延。因此使用脚本要更简单,速度更快
复用。客户端发送的脚本会永久存在redis中,这样,其他客户端可以复用这一脚本而不需要使用代码完成相同的逻辑。
香吗?真香!反正用过的都说好。可以看到相比命令模式还是优势还蛮大的。
那么Lua脚本要怎么用呢?下面跟大家介绍几个常见的常用的命令:
EVAL
EVAL 可以理解为是lua脚本的解释器,它的语法格式如下:
EVAL script numkeys key [key ...] arg [arg ...]
- script:一段 Lua 脚本或 Lua 脚本文件所在路径及文件名。
- numkeys:Lua 脚本对应参数数量
- key [key …]:Lua 中通过全局变量 KEYS 数组存储的传入参数
- arg [arg …]:Lua 中通过全局变量 ARGV 数组存储的传入附加参数
官方腔有点重对吧,没事,咱们来看个例子:
eval