Redis的事务是什么样子的?Redis的事务和MySql的事务的区别在哪?watch命令的作用是什么?

Redis 的事务

Redis 的事务和 Mysql 的事务意思都是一样的,都表示把一系列的操作绑成一组,让这一组能够批量执行。

但是,Redis 的事务和 Mysql事务,有一些区别:

Redis 是“弱化的原子性”,相比于 Mysql 而言,Mysql 的原子性就是保证了一组操作,要么全都执行成功,要么全都执行失败,如果执行失败,还会涉及到回滚操作,而 Redis 的原子性仅仅只是保证了一组操作批量执行,失败或者成功,它并不会关心,就算失败了也没有回滚操作。

Redis 不保证一致性,因为,在 Redis 中不涉及到“约束” 和 “回滚” 操作,相比于MySQL 而言,MySQL 的一致性体现的就是事务运行前和运行后,结果都是合理有效的。

Redis 不具备隔离性,因为 Redis 是单线程模型,所以不会并发事务

Redis 的事务不具备持久性,因为 Redis 中的数据是保存在内存中的,虽然 Redis 也有持久性机制,可以通过 开启 AOF 或者 生成 RDB 文件,但是,如果把 AOF 关闭,或者不进行 RDB 持久化操作,那么它就不会进行持久化,而相比较MySQL来说,MySQL 在执行事务时,就直接把数据存储到了硬盘中,所以,Redis 的持久化和事务是没有什么关系的。

所以,Redis 的事务主要的意义主要是将一组操作批量执行,避免被其他客户端进行插队。

Redis 是如何实现事务的?

Redis 中实现事务,是针对每个开启事务的客户端,引入了一个存储事务的队列,此时客户端输入的命令,就会发给服务器并且进入这个队列,但是,此时队列中的任务也不是说立即就执行的,而是在当遇到“执行事务”命令的时候,此时就会把队列中的这些任务都按照顺序依次执行,所以,这就跟“多线程”中的加锁是以这样的,多线程使用加锁避免多个线程插队,Redis 就是使用事务避免了多个客户端插队。

Redis 的事务为啥搞得这么简单,为啥不设计成和MySQL一样强大呢???

如果想把某些功能设计的比较强大,肯定是要付出代价的,Mysql 的事务,在背后就付出了很大的代价,比如,MySQL的回滚操作,就要在额外开辟一块空间,来记录一些日志,记录一下每一步回退,在空间以及时间上都有很大的开销,所以,正因为这些原因,才有了Redis上场的机会。

啥时候使用 Redis 的事务呢???

如果我们只是需要把多个操作打包进行,使用 Redis 的事务是比较合适的,例如 “超卖场景”。

例如:现在有一款手机,只放货了 500 台,但如果让 501 个人下单成功,就构成了超卖。

比如,我现在有一种典型的写法来记录这 500 台手机的个数:

在这里插入图片描述

在这里插入图片描述

Redis 在集群环境中部署时,就无法使用“事务”

Redis 中事务的操作命令

开启事务

MULTI

从下图可以看到,在开启事务后,set 命令并没有生效,只是返回了一个 queued,这就说明,当前的命令,只是被放入了事务队列中,并没有生效,此时,如果通过另一个客户端获取的话是获取不到的。

在这里插入图片描述

执行事务

EXEC

输入 exec 命令之后,队列中的命令就会全部执行。

在这里插入图片描述

放弃当前事务

discard

在这里插入图片描述

当开启时候后,并且给服务器发起若干个命令之后,此时服务器重启了,此时的这个事务咋办???

此时的效果其实就等同于 discard

watch 命令

watch的作用:监控某个 key 是否在执行事务之前发生了改变

如下图:

有这样一种场景,客户端1开启了事务,并且设置了 key,但是,在执行事务之前,客户端2 修改了key,此时,按照常理来讲,key 应该是 222,但是,因为在客户端1中,只是将命令放到了队列中,并没有实际的去执行,只有在输入 exec 命令之后,才会执行,所以,最终的 key 的 value 是 111

在这里插入图片描述

对于上述这种在事务执行完之前,但key 发生了变化,此时就可以使用 watch 进行监控,如下图:

当 watch 监控了 key ,开启事务之后,在 set key 111 执行前,在另一个客户端中对 key 进行了修改,当在客户端1中,输入 exec 命令执行事务的时候,就会执行失败,如果没有使用 watch 进行监控的话,最后key 的value值就是 111

在这里插入图片描述

watch 的实现原理

watch 是基于版本号机制实现的,如下图:

例如,在执行 watch key 时,会给 key 设置一个“版本号”,可以理解成是一个整数,每次修改 key ,版本号都会变大。

假设,初始情况下,key 的版本号为 1,如果,从事务开启时到事务执行之前,对 key 进行了修改,此时 key 的版本号就会变大,当执行事务时,也就是 exec 时,就会判断一下,当前 key 的版本号和key watch 时的初始版本号是否一致,如果一致,才会真正的设置,如果不一致,则返回nil
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值