Redis事务

一、Redis事务特性

MySQL事务有四种特性,分别是原子性、持久性、隔离性以及一致性,而redis相对而言,事务则简单得多。

Redis事务具有弱化的原子性,它可以把多个操作打包到一起,要么全部执行,要么全部都不执行,它不保证执行成功,而MySQL是要保证成功的,不成功就会回滚,Redis没有回滚特性,所以说它是弱化的原子性

Redis事务不具有一致性,Redis没有约束,也没有回滚机制,事务执行过程中,如果某个修改操作出现失败,就可能导致不一致的情况

Redis事务不具有持久性,Redis本身就是内存数据库,数据是存储在内存中的,虽然Redis有持久化机制,但这里的持久化机制和事务没有直接关系

Redis事务不具有隔离性,Redis是一个单线程模型的服务器程序,所有的请求/事务,都是"串行"执行的

二、为什么要有事务

既然Redis事务和MySQL事务相差甚远,为什么还要有呢?

Redis事务,主要的意义就是为了"打包",避免其它客户端的命令,插队插到中间。

Redis中实现事务,是引入了队列,每个客户端都有一个,开启事务的时候,此时客户端的命令,就会发给服务器,并且进入这个队列中,而不是立即执行,当遇到"执行事务"命令的时候,就会把队列中的这些任务都按照顺序依次执行,是在Redis主线程中执行的,主线程会把事务中的操作都执行完,再处理别的客户端

Redis的事务为何不设计成像MySQL事务一样强大呢?

主要是因为MySQL实现事务,是付出了巨大的代价的,包括时间上,有更大的执行开销;空间上,要花费更多的空间来存储更多的数据

三、Redis事务的适用场景

比如在抢购某件东西的时候,它放货5000件,如果是按照下图中的这种做法,就会出现线程安全问题,可能卖出5000+件东西,以前在多线程的场景下,是通过加锁实现的,但这里Redis事务就能派上用场啦!

在这里插入图片描述
具体做法:第二个客户端的"执行事务"命令发过来之后,服务器才开始真正执行第二个事务中的内容,此时第一个事务执行事务命令已经运行过了,第二个事务get到的count就已经是第一个事务自减之后的结果了!
在这里插入图片描述
上面的if判断语句,在Redis命令中是没有的,但是redis支持lua脚本,通过lua脚本就可以实现上述的条件判定,并且也和事务一样,是打包批量执行的!

四、实战演练

开启事务:MULTI
执行事务:EXEC
放弃当前事务:DISCARD

如下图,当一个客户端没有执行exec的时候,另一个客户端是无法知道其它客户端的修改的

在这里插入图片描述
当执行事务命令完成后,也就可以看到了!!!

在这里插入图片描述
当开启事务,并且给服务器发送若干命令后,服务器重启,此时的效果就等同于discard命令

在这里插入图片描述

五、WATCH命令

如下图,从时间上来看,客户端1先发送了set key 222,客户端2最后发送了set key 333,由于客户端1中,得是exec执行了,才会执行set key 222,所以这个操作就变成了实际上更晚执行的操作,最终值就是222
在这里插入图片描述

在这里插入图片描述
如果想解决上述这个问题,就可以用WATCH来监控某个key是否在事务执行之前,发生了改变,如下图所示

在这里插入图片描述
WATCH的实现

WATCH的实现,类似于一个 “乐观锁”

乐观锁、悲观锁,不是指某个具体的锁,而是指的是某一类锁的特性

乐观锁:加锁之前,就有一个心理预期,预期接下来锁冲突的概率比较低

悲观锁:加锁之前,也有一个心理预期,接下来锁冲突的概率比较高。比如两个线程针对同一把锁,一个能加锁成功,另一个就得阻塞等待

锁冲突概率高和冲突概率低,接下来要做的工作是不一样的!!!

redis的watch,就相当于是基于版本号这样的机制,来实现了"乐观锁"

如下图,假定初始版本号为1,版本号可以理解成一个"整数",每次修改的时候都会"变大"(具体是变大还是变小得看源码的具体实现,这里假定变大)!当执行exec的时候,判断WATCH时key的版本号,和当前key的版本号是否一致,一致,说明当前key在事务开启到最终执行这个过程中,没有别的客户端对key做出修改,于是才能进行设置;不一致,就说明key在其它客户端中修改过了,此处就直接丢弃事务中的操作,exec返回nil

在这里插入图片描述
从上述可看出,WATCH本质是给exec加了个判定条件

注意:WATCH必须搭配事务适用,并且必须在MULTI之前使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值