redis的事务系列文章目录

文章目录

  • redis的事务系列文章目录
  • 前言
  • 第一种情况:组队成功 exec
  • 第二种情况:组队不成功,队伍解散
  • 第三种情况:编译时不报错就执行,与MySQL不同,不回滚
  • redis里面为什么要有事务
  • 悲观锁和乐观锁
  • 悲观锁和乐观锁的使用
  • 关系型数据库基本上都是悲观锁,比如mysql和oracle,非关系型数据库redis是乐观锁
  • 在redis中怎么体现乐观锁
  • 代码演示锁

前言

redis的事务是什么,它跟mysql的事务是一样的吗?

实际上redis的事务和mysql的事务是不一样的,我们不能把他们混为一谈,应该分开来理解

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号

第一种情况:组队成功 exec

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号_02


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号_03


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_04


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_05


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_06

第二种情况:组队不成功,队伍解散

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_07


multi在组队的过程中只要有一条语句报错了,队伍就会解散,队伍解散之后,所有队列都作废了

解散以后,你再怎么执行exec都不会成功了

第三种情况:编译时不报错就执行,与MySQL不同,不回滚

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号_08


组队的时候没有发现语法错误的话,执行的时候我就不管,直接给你执行了

那么这是不是说明redis中没有回滚这个功能呢?

可以百度看一下

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_redis_09

redis里面为什么要有事务

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号_10


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_11

悲观锁和乐观锁

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号_12


悲观锁不允许并发执行,而乐观锁是可以并发执行的

乐观锁即我始终认为你这个账户不会有人去操作,每个人都可以去拿

如下图,假设你有10000块,你的前女友双十一买东西,发过来一个请求,需要8000,前前女友要买包包需要2000

这个时候他们俩谁先抢到,就看谁的手速了,那么假设前女友快一些,扣掉了8000剩余2000,那么此时你的账户就会默认逻辑上加了一个版本号 v1.1

这个时候前前女友的请求就会去对比版本号,v1.0 对不上v1.1,这个时候,她的操作就会失败,以此类推,不断的加版本号,这就叫乐观锁过年过节买火车票就是这样的一个场景

我们买火车票的时候比如8点放票,这个时候大家都能看到票,只是看谁手速快,看谁先下订单

所以有时候8点踩点来抢票的人很难抢到票,而后面来的人反而比较容易抢到票,因为最先来的人版本号是V1.0,已经不通过了,所以如果抢票来早了,又没有抢到票,那么就重新进一下,更新一下版本号,很大可能会更容易抢到票

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_13

悲观锁和乐观锁的使用

关系型数据库基本上都是悲观锁,比如mysql和oracle,非关系型数据库redis是乐观锁

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_14

在redis中怎么体现乐观锁

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_15


如下图:假定有2个进程,如果没有锁,拿到的数据会是多少

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_16


如果没有锁机制,拿到的数据可能会是1100 也可能会是1200,也可能是1300

所以我们需要事务,让他们一块执行

上图中第二个进程,也可以进行数据增长

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_redis_17


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_18

代码演示锁

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_redis_19


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_redis_20

注意上锁/监听 watch 要结合 事务 multi 来使用

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号_21


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号_22


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_23


不管开多少个进程,在执行之前,大家都一样,但是执行之后,只有一个能够成功,因为成功那个更改了乐观锁的版本号,导致其它的匹配不了最新的版本号,所以其它的会执行失败

而最终只有一个能够成功

redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_版本号_24


redis08_redis的事务 multi(声明一个事务)、exec(执行一个事务)、redis里面为什么要有事务、悲观锁和乐观锁(可以并发提高吞吐量)_乐观锁_25