Redis 事务

介绍

可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞!

能干嘛

一个队列中,一次性、顺序性、排他性的执行一系列命令。

怎么玩

常用命令

在这里插入图片描述

正常执行

-- 开启事务
multi

--关闭事务
exec

在这里插入图片描述

我们结束事务之后再使用 keys * ,可以发现刚才在事务中写入的数据是存在的!

放弃事务

-- 放弃事务
discard

在这里插入图片描述

因为我们放弃了事务,所以刚才的写操作不会被执行,查出来的还是我们第一次写入的 v2

全体连坐

全体连坐,顾名思义就是指在事务执行的时候如果其中有一个地方出错,那么不管其它的操作能不能正常执行,一律都不会被执行!

在这里插入图片描述

上图圈起来的部分可以看到,我们不按格式去给他执行操作,出现了错误,这个时候它不会直接给你跳出来,而是可以继续进行执行操作,但是在我们退出来的时候就会提示 “EXECABORT事务由于先前的错误而被丢弃”!也就表示里面的操作都已经被丢弃了,不会被执行!

冤头债主

顾明思议就是指谁出错谁就不被执行,而成功的就照成执行

在这里插入图片描述

因为我们在之前给 k1 设置的值为 v1,是非整数类型,所以执行 incr 的时候就会导致报错!

执行完后我们可以发现除了 incr 那一行以外,其他的部分都正常执行了!

但是这里大家可能会有点好奇,为什么之前在事务中执行错误的命令会导致全部不执行,而这里却只是单独的不执行呢?

因为在 redis 中,事务是部分支持的,而不是全部都支持,所以在 incr 命令执行错误的时候只会让它单独执行失败,而不会影响到其它的命令执行!

watch监控

悲观锁

顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会进入等待直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁

顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。

乐观锁策略:乐观锁会在每条记录的后面加上一个版本号,提交的版本号必须大于记录的当前版本号才能执行更新!

并发性和一致性的对立

假设我们现在有一张表,有n条记录

乐观锁和悲观锁有点像数据库中的行锁和表锁

表锁:给整张表加锁,表示一旦上锁,当前表只能允许我自己修改,别人不能修改!虽然这样很好的保证了安全性,基于少数记录时还好,但是如果有几万或几十万条记录,这个时候我们需要修改666行记录的数据,别人又无法进行修改,这个时候操作就会处于排队状态,一两个还好,但是一直累积,到最后压力过大导致宕机!所以并发性差,但一致性好。

行锁:给某行加锁,

CAS
例子:初始化信用卡可用余额和欠额

比如我这个月借了10块钱花呗,那么我下个月就需要还10块钱。也就是需要一边扣除余额,一边增加欠额

在这里插入图片描述

这种情况在 redis 当中就需要将这两个操作放进同一个事务中进行处理,执行完了之后一边减一边增。在执行的时候就需要进行监控

-- 监控对应key值
watch key

在这里插入图片描述

我们可以看到,结束事务之后正常修改了余额和欠额

在这里插入图片描述

上图可以看到,我们监控后就表示给该key值加了锁,在加锁状态下修改了它的数据,然后在启动事务进行借钱操作,这样是不会正常执行的,因为它需要先获取到最新的值才能够去进行事务提交。

:此处我启动了两个redis(一个在VM,一个在Xshell),大家不要觉得我只启动了一个redis来执行。

在这里插入图片描述

上图可以看到,我们在监控下修改余额之后,我们直接使用 unwatch 停止本次的监控(因为不停止就会出现刚才的错误),然后再次开启监控,这个时候我们开启事务修改余额和欠额,最后关闭事务就可以发现都执行成功了!这是因为停止后数据会获取到最新的,然后我们在去进行监控的时候就已经是最新的数据了,所以就可以正常的修改里面的数据!

PS:还有一个需要知道的就是,我们在执行 exec 或者 unwatch 命令的时候之前的监控锁都会被自动取消掉!

3 阶段-回顾

开启

以 multi 开启事务

入队

将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面

执行

有 exec 命令触发事务

3 特性-回顾

  1. 单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  2. 没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题
  3. 不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值