• 注册
  • 后端开发博客 后端开发博客 关注:0 内容:623

    Redis中实现事务和乐观锁–Redis实战(五)|Java 开发实战

  • 查看作者
  • 打赏作者
  • 当前位置: 职业司 > 后端开发 > 后端开发博客 > 正文
    • 后端开发博客
    • 这是我参与更文挑战的第5天,活动详情查看: 更文挑战

      本文正在参加「Java主题月 - Java 开发实战」,详情查看 活动链接


      相关文章

      Redis实战汇总:Redis实战


      前言

      • 事务

      原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。

      一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

      隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

      持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

      在Redis事务没有没有隔离级别的概念!

      在Redis单条命令式保证原子性的,但是事务不保证原子性

      • 乐观锁

      ①当程序中可能出现并发的情况时,就需要保证在并发情况下数据的准确性,以此确保当前用户和其他用户一起操作时,所得到的结果和他单独操作时的结果是一样的。

      ②没有做好并发控制,就可能导致脏读、幻读和不可重复读等问题。

      在Redis是可以实现乐观锁的!

      一、Redis如何实现事务?

      ①正常执行事务

      127.0.0.1:6379> multi  #开启事务
      OK
      127.0.0.1:6379> set name dingyongjun  #添加数据
      QUEUED
      127.0.0.1:6379> set age 26  #添加数据
      QUEUED
      127.0.0.1:6379> set high 172  #添加数据
      QUEUED
      127.0.0.1:6379> exec  执行事务
      1) OK
      2) OK
      3) OK
      127.0.0.1:6379> get name  #获取数据成功,证明事务执行成功
      "dingyongjun"
      127.0.0.1:6379> get age
      "26"
      复制代码

      ②放弃事务

      127.0.0.1:6379> multi  #开启事务
      OK
      127.0.0.1:6379> set name dingyongjun  #添加数据
      QUEUED
      127.0.0.1:6379> set age 26  #添加数据
      QUEUED
      127.0.0.1:6379> discard  #放弃事务
      OK
      127.0.0.1:6379> get name  #不会执行事务里面的添加操作
      (nil)
      复制代码

      ③编译时异常,代码有问题,或者命令有问题,所有的命令都不会被执行

      127.0.0.1:6379> multi  #开启事务
      OK
      127.0.0.1:6379> set name dingyongjun  #添加数据
      QUEUED
      127.0.0.1:6379> set age 23  #添加数据
      QUEUED
      127.0.0.1:6379> getset name  #输入一个错误的命令,这时候已经报错了,但是这个还是进入了事务的队列当中
      (error) ERR wrong number of arguments for 'getset' command
      127.0.0.1:6379> set high 173  #添加数据
      QUEUED
      127.0.0.1:6379> exec  #执行事务,报错,并且所有的命令都不会执行
      (error) EXECABORT Transaction discarded because of previous errors.
      127.0.0.1:6379> get name  #获取数据为空,证明没有执行
      (nil)
      复制代码

      ④运行时异常,除了语法错误不会被执行且抛出异常后,其他的正确命令可以正常执行

      127.0.0.1:6379> multi  #开启事务
      OK
      127.0.0.1:6379> set name dingyongjun  #添加字符串数据
      QUEUED
      127.0.0.1:6379> incr name  #对字符串数据进行自增操作
      QUEUED
      127.0.0.1:6379> set age 23  #添加数据
      QUEUED
      127.0.0.1:6379> get age  #获取数据
      QUEUED
      127.0.0.1:6379> exec  #执行事务。虽然对字符串数据进行自增操作报错了,但是其他的命令还是可以正常执行的
      1) OK
      2) (error) ERR value is not an integer or out of range
      3) OK
      4) "23"
      127.0.0.1:6379> get age  #获取数据成功
      "23"
      复制代码

      ⑤总结:由以上可以得出结论,Redis是支持单条命令事务的,但是事务并不能保证原子性!

      二、Redis如何实现乐观锁?

      ①watch(监视)

      127.0.0.1:6379> set money 100  #添加金钱100
      OK
      127.0.0.1:6379> set cost 0  #添加花费0
      OK
      127.0.0.1:6379> watch money  #监控金钱
      OK
      127.0.0.1:6379> multi  #开启事务
      OK
      127.0.0.1:6379> DECRBY money 30  #金钱-30
      QUEUED
      127.0.0.1:6379> incrby cost 30  #花费+30
      QUEUED
      127.0.0.1:6379> exec  #执行事务,成功!这时候数据没有发生变动才可以成功
      1) (integer) 70
      2) (integer) 30
      复制代码

      ②多线程测试watch
      #线程1

      #线程1
      127.0.0.1:6379> set money 100  #添加金钱100
      OK
      127.0.0.1:6379> set cost 0  #添加花费0
      OK
      127.0.0.1:6379> watch money  #开启监视(乐观锁)
      OK
      127.0.0.1:6379> multi  #开启事务
      OK
      127.0.0.1:6379> DECRBY money 20  #金钱-20
      QUEUED
      127.0.0.1:6379> INCRBY cost 20   #花费+20
      QUEUED
      #这里先不要执行,先执行线程2来修改被监视的值
      127.0.0.1:6379> exec  #执行报错,因为我们监视了money这个值,如果事务要对这个值进行操作前
      #监视器会判断这个值是否正常,如果发生改变,事务执行失败!
      (nil)
      复制代码

      #线程2

      #线程2,这个在事务执行前操作执行
      127.0.0.1:6379> INCRBY money 20  #金钱+20
      (integer) 120
      复制代码

      ③总结:乐观锁和悲观锁的区别。
      悲观锁: 什么时候都会出问题,所以一直监视着,没有执行当前步骤完成前,不让任何线程执行,十分浪费性能!一般不使用!
      乐观锁: 只有更新数据的时候去判断一下,在此期间是否有人修改过被监视的这个数据,没有的话正常执行事务,反之执行失败!


      路漫漫其修远兮,吾必将上下求索~
      到此关于Redis的事务和乐观锁的讲解就算告一段落了,如果你认为i博主写的不错!写作不易,请点赞、关注、评论给博主一个鼓励吧~

      请登录之后再进行评论

      登录

      手机阅读天地(APP)

      • 微信公众号
      • 微信小程序
      • 安卓APP
      手机浏览,惊喜多多
      匿名树洞,说我想说!
      问答悬赏,VIP可见!
      密码可见,回复可见!
      即时聊天、群聊互动!
      宠物孵化,赠送礼物!
      动态像框,专属头衔!
      挑战/抽奖,金币送不停!
      赶紧体会下,不会让你失望!
    • 实时动态
    • 签到
    • 做任务
    • 发表内容
    • 偏好设置
    • 到底部
    • 帖子间隔 侧栏位置:
    • 还没有账号?点这里立即注册