请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

redis事务

一哥:
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!共同建造、维护这门课程,我需要每一个你!

1 回复 有任何疑惑可以回复我~
  • 提问者 阿斯拉菲 #1
    1024!非常感谢
    回复 有任何疑惑可以回复我~ 2020-10-13 11:47:10
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信