【Redis】事务

🐼什么是事务,事务的特性

Redis 的事务和 MySQL 的事务概念上是类似的. 都是把⼀系列操作绑定成⼀组. 让这⼀组能够批量执行,也就是将一组 命令进行了打包

MySQL有四个特性,我们知道,比如原子性,持久性,隔离性,一致性。那么Redis呢?

Redis有一致性吗?隔离性吗?原子性吗?持久性吗?

首先我们来说一下Redis有没有原子性。看了MySQL原子性的定义,就知道redis有没有原子性的特点了。

MySQL对原子性的定义:把多个操作打包在一起,要么全部执行成功,要么全部不执行。(如果执行操作失败,那么就会进行回滚操作)

Redis对原子性的定义:把多个操作打包在一起,要么全部执行但不保证成功,要么全部不执行。(如果执行失败,那就失败吧,不会有回滚的操作了)

现在应该很清楚了,redis只保证了他能帮你把这一组命令打包然后执行,保证了这些命令的执行顺序是连续的, 中间不会插入任何一条命令 ,但是执行的对不对 ,就与我无瓜了。

所以redis具有原子性嘛?已经可以称得上是原子的了,可是MySQL这个"标杆",就使得redis的原子性好像有,但又那么弱。所以,一般我们说原子性,一般是能够**打包+回滚(打包一起正确执行)**才称的上原子性。

💮所以,对于redis是否具有原子性,那么就看你的理解咯~仁者见仁智者见智

💮redis没有约束,也没有回滚机制,如果事务在执行过程中哪一步 发生了错误,就可能影响到正确结果,当然保证不了数据的一致性,所以redis不具有一致性

💮redis本身就是内存级的数据库,数据都是在内存中存储的,虽然Redis也有持久化机制,但是和这里的事务的持久化可无关,所以,不具有持久性

💮隔离级别本质就为了保证多个MySQL客户端并发请求同一组数据,导致数据的错误而设立的一种机制,随着隔离级别的增加,但是效率反而降低了,包括但不亚于脏读幻读不可重复读。redis是一个单线程 的服务器程序,所有的请求/事务,都是串行 执行的,当然不会有并发冲突了,所以没有隔离性一说了,隔离性有点多余了~

所以,Redis这么一和MySQL比,好像就是个弟弟,给我们的感觉。可是,凡事不能一锤子定死,就像UDP和TCP,你说UDP不保证可靠性,但是快啊,不保证可靠性不是缺点,而是UDP的特点。Reids也是,Redis这样的事务设定也是特点

正是因为MySQL要保证回滚机制,保证数据一致性,保证持久化,有了隔离性,所以慢啊,这是缺点嘛?不是,这也是特点啊!所以,Redis才有了上场机会

所以,Redis的事务,就是为了**"打包"** ,在执行一组命令的时候,避免 其他客户端,进行**"插队"**

仅此而已~


🐼Redis实现事务

Redis实现事务的目的就是如何事务的本质,Redis为了实现事务,在服务器上搞了⼀个**"事务队列"** . 每次客户端在事务中进行⼀个操作, 都会把命令先发给服务器, 放到 "事务队列" 中(但是并不会立即执行),而是会在真正收到 EXEC 命令之后, redis主线程才真正执行 队列中该客户端所有 操作,执行完再执行其他客户端.

什么叫做真正收到了EXEC命令之后,才真正执行?我们先看一下事务的操作


🐼Redis事务操作

cpp 复制代码
MULTI (maoti)

开启⼀个事务. 执行成功返回 OK.

cpp 复制代码
EXEC

真正执行事务.

我们现在解决一下什么叫做真正执行事务,回答上面的问题:

如图:

现在有两个客户端同时请求redis-server,客户端一开启了事务,并且设置了key = 222,在客户端一执行exec之前,客户单而来了一个请求set key = 333,那么到底redis-server先执行谁?

从时间轴上看,好像是客户端一先发送了set key 222,客户端2后发送了set key 333,但是由于客户端一得是exec执行了,才会真正执行set key 222,这个操作反而变成了更晚的操作,最终值就是key = 222

如图:

cpp 复制代码
DISCARD

放弃当前事务. 此时直接清空事务队列. 之前的操作都不会真正执行到.

还有一个操作会触发这个场景,比如,在开启事务,给服务器发送了一大堆的请求,此时服务器重启了,此时的效果就类似于discard

cpp 复制代码
WATCH

✅监控某个key,是否在事务执行之前(exec) ,就发生了修改。在此时就容易出现数据不⼀致的问题,此时watch就派上用场了.注意执行watch命令要在MULTI之前执行。

对于上面的例子,这个时候, 其实就容易引起歧义.其实我们很难知道到底数据被修改为了222,还是333。watch就是解决这个问题的

因此, 即使不保证严格的隔离性, ⾄少也要告诉⽤⼾, 当前的操作可能存在⻛险.

还是上面的例子,客户端一监控了key,还没来得及exec,但客户端2已经对key修改了,此时客户端一执行了exec,返回nil,此时客户端一就知道了,在我执行事务期间,有别的客户端跟我写入了同一个key了,没有执行成功。

bash 复制代码
UNWATCH

✅取消对 key 的监控.

相当于 WATCH 的逆操作


🌏这里浅浅谈一嘴watch的实现。

watch的实现,类似于一个"乐观锁".

乐观锁和悲观锁是什么,这里就不细谈了,总之,知道,他俩都不是指某一个具体的锁,而是锁的一种特性。

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

悲观锁:加锁之前,就要有一个心理预期,预期接下来锁冲突的概率高。

redis中的watch相当于实现版本号,这样的机制,来实现的"乐观锁"。

如图所示

最后,redis中任何关于事务能够实现的效果,都能使用lua脚本替代。

相关推荐
野犬寒鸦2 小时前
从零起步学习MySQL || 第十六章:MySQL 分库分表的考量策略
java·服务器·数据库·后端·mysql
cyhysr2 小时前
2025sql大赛题:仅用sql处理数独
数据库·sql·oracle
知识分享小能手2 小时前
Oracle 19c入门学习教程,从入门到精通, —— 知识点详解(1)
数据库·学习·oracle
BD_Marathon2 小时前
搭建MyBatis框架之创建MyBatis的映射文件(五)
java·数据库·mybatis
橘子真甜~2 小时前
Reids命令原理与应用5 - Redis 主从同步与高可用集群
运维·网络·数据库·redis·缓存·redis集群·redis高可用
2501_948194982 小时前
RN for OpenHarmony AnimeHub项目实战:放送时间表页面开发
数据库·redis·缓存
松涛和鸣2 小时前
DAY52 7-Segment Display/GPIO/Buttons/Interrupts/Timers/PWM
c语言·数据库·单片机·sqlite·html
想摆烂的不会研究的研究生2 小时前
每日八股——Redis(3)
数据库·redis·后端·缓存
寂寞恋上夜2 小时前
数据迁移方案怎么写:迁移策略/回滚方案/验证方法(附完整模板)
网络·数据库·oracle·markdown转xmind·deepseek思维导图