redis事务
来源:10-2 使用了事务功能,怎么没回滚呢?
阿斯拉菲
2020-10-12
一哥:
redis的事务不支持回滚,但可以保证操作的原子性。
Q:
1、我们在实现redis锁普遍的做法是用lua来保证操作的原子性,为啥不用redis自带的事务呢?
2、redis事务执行一半不回滚,那lua脚本执行一半的情况呢?
3、redis事务的使用场景
1回答
-
阿斯拉菲同学你好:
首先需要说明的是,Redis 事务在企业级开发中,使用的频率还是很高的。但是,我同样在课程中说明了为什么不需要考虑回滚,原因很简单:为什么会出错?是因为你的代码写的有问题,如果代码没问题,那么,机器宕机、网络失效等等你几乎可以忽略,这些基本停留在理论层面。
下面,我开始回复你的问题:
第一:我们在实现 redis 锁普遍的做法是用 lua 来保证操作的原子性,为啥不用 redis 自带的事务呢?
前半段,为什么在实现分布式锁的时候,要使用 LUA 脚本呢?我们先来看看不使用 LUA 脚本,会写出类似如下的代码:
if (setnx(key, 1) == 1){ expire(key, 30) try { //TODO 业务逻辑 } finally { del(key) } }
但是,这样的实现存在问题:setnx 和 expire 不是原子执行的,如果 SETNX 成功,在设置锁超时时间后,服务器挂掉、重启或网络问题等,导致 EXPIRE 命令没有执行,锁没有设置超时时间变成死锁。
所以,就会有人选择使用 LUA 脚本来完成这段代码:
if (redis.call('setnx', KEYS[1], ARGV[1]) < 1) then return 0; end; redis.call('expire', KEYS[1], tonumber(ARGV[2])); return 1; // 使用实例 EVAL "if (redis.call('setnx',KEYS[1],ARGV[1]) < 1) then return 0; end; redis.call('expire',KEYS[1],tonumber(ARGV[2])); return 1;" 1 key value 100
但是,Redis在 2.6.12 版本开始,为 SET 命令增加了一系列选项:
SET key value [EX seconds][PX milliseconds][NX|XX]
EX seconds:设置指定的过期时间,单位秒。
PX milliseconds:设置指定的过期时间,单位毫秒。
NX:仅当key不存在时设置值。
XX:仅当key存在时设置值。
所以,都没有必要再去使用 LUA 脚本了,一个命令也就搞定了。所以,你也就明白了,一条命令就可以执行完的事,你为什么还要使用 Redis 的事务呢?
第二:redis 事务执行一半不回滚,那 lua 脚本执行一半的情况呢?
其实你这里的问题已经说明一切了,LUA 脚本只是脚本,它执行出错也就停止了,根本就不存在事务,当然也就不存在回滚的说法了。
第三:redis 事务的使用场景
我们从名字可以看出来,Redis 事务也是事务,它支持事务的大部分特性,但是回滚不支持。所以,你可以知道,如果你的请求并发量很大,很多操作都需要在内存中去完成,那么,使用 Redis 是很好的选择。那么,如果多个操作需要是原子执行,当然就需要去考虑 Redis 事务。但是,你需要尽可能保证你的代码不会出现问题,且有补救的措施(记录日志、报警等等)。
但是,如果你还涉及不到高并发之类的业务系统,你大概率应该接触不到 Redis 事务。
我是勤一,致力于将这门课程的问答区打造为 Java 知识体系知识库,Java 知识体系 BBS!共同建造、维护这门课程,我需要每一个你!
112020-10-13
相似问题