【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脚本替代。

相关推荐
D4c-lovetrain2 分钟前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希39 分钟前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神43 分钟前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员1 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java1 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿1 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴1 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存
YOU OU1 小时前
三大范式和E-R图
数据库
一江寒逸1 小时前
零基础从入门到精通MySQL(上篇):筑基篇——吃透核心概念与基础操作,打通SQL入门第一关
数据库·sql·mysql
@土豆2 小时前
Ubuntu 22.04 运行 Filebeat 7.11.2 崩溃问题分析及解决文档
linux·数据库·ubuntu