redis - 事务

什么是事务

事务,在mysql中也有这样的概念。其中事务包括4个概念,原子性、一致性、持久性和隔离性。原子性就是将多个操作,打包成为一个整体执行,要么执行成功,要么执行失败。

一致性是指事务执行之后,数据依旧保持完整。

持久性 是在事务中的修改或写入都会存到硬盘中。

隔离性 是指在事务并发执行时,防止因交叉执行而导致数据不一致。

然后接下来是对比redis事务和mysql事务的不同。

弱化的原⼦性:关于原子性,mysql是将多个操作打包成一个操作,要么执行成功,要么执行失败。如果执行失败,就进行回滚操作,就是将事务操作中的已经执行的操作,全都进行回退。

而redis的 原子性是将多个操作打包成一个操作,要么全部执行,要么全都不执行。这里并没有和mysql一样保证执行成功,更没有mysql的回退机制。所以redis的原子性是一种弱化的原子性。

不保证⼀致性: redis事务不涉及 "约束". 也没有回滚. MySQL 的⼀致性体现的是运⾏事务前和运⾏后 , 结果都 是合理有效的, 不会出现中间⾮法状态。

不需要隔离性: 也没有隔离级别, 因为不会并发执⾏事务 (redis 单线程处理请求,所有请求/事务都是串行执行的) 。

不需要持久性: 是保存在内存的. 是否开启持久化, 是redis-server ⾃⼰的事情, 和事务无关。

Redis 事务本质上是在服务器上搞了⼀个 "事务队列"。 每次客户端在事务中进⾏⼀个操作,都会把命令先 发给服务器, 放到 "事务队列" 中(但是并不会⽴即执行) ⽽是会在真正收到 EXEC 命令之后, 才真正执行队列中的所有操作。

因此, Redis 的事务的功能相⽐于 MySQL 来说, 是弱化很多的. 只能保证事务中的这几个操作是 "连续 的", 不会被别的客⼾端 "加塞", 仅此⽽已。

redis事务命令

MULTI

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

每次添加⼀个操作, 都会提⽰ "QUEUED", 说明命令已经进⼊客⼾端的队列了,但是并未被执行。

新开一个客户端,是查不到这样的数据的。

EXEC

真正执⾏事务。

执⾏ EXEC 的时候, 客⼾端才会真正把上述操作发送给服务器,执行队列中的操作。

在另外的客户端就能查看到设置的数据了

DISCARD

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

开启事务,并且给服务器发送若干个命令之后,此时服务器重启了。情况就等同discard的效果。

WATCH

在执行事务的时候, 如果某个事务中修改的值, 被别的客户端修改了, 此时就容易出现数据不⼀致的问 题。

watch必须搭配事务使用,并且必须在multi之前使用。

场景

从时间上来看,客户端1是先发送了set key 222,客户端2 是后发生了 set key 333

由于客户端中,是执行exec执行了,才会真正执行 set key 222,这个操作变成了实际上更晚执行的操作,最终值就是 222。

在上面的场景中,就可以使用watch命令来监控这个key,看看这个key在事务的multi和exec之间,是否在外部被其他客户端修改了。如果没修改了,给出提示信息

客户端1

客户端2在客户端1 set key 222之后,执行 set key 333,

然后在客户端1提交事务,再查看key

UNWATCH

取消对 key 的监控。相当于 WATCH 的逆操作

WATCH的实现原理

watch的实现,类似于一个"乐观锁"。乐观锁和悲观锁不是指具体的锁,而是指某一类锁的特性。

乐观锁:加锁之前,预期接下来锁冲突的概率比较低

悲观锁:加锁之前,预期接下来锁冲突的概率比较高

而锁的冲突概率高,和冲突概率低,所要做的工作是不一样的。C++、Linux涉及到的锁 mutex / std::mutex 都是悲观锁,Java synchronized 则是可以在乐观和悲观之间自适应的。

redis 的watch实现就相当于 基于版本号 的机制去实现乐观锁。

执行watch key的时候,就会给这个key安排一个版本号,并且记录下来。(这个版本号可以理解成一个"整数",这个整数在key每次修改的时候,都会"变大")。

在执行exec的时候,判定当前key的版本号和最初watch时的版本号是否一致,如果一致,说明当前key在事务开启到最终执行过程中,没有其他客户端修改,于是才能真正进行设置。如果不一致,不一致,说明key在其他客户端进行了修改,就直接丢弃事务中的操作,并且exec返回一个nil。也就是说watch本质是给exec加了个判定条件

相关推荐
java_logo4 小时前
Apache Doris Docker 部署指南:实时分析数据库实战
数据库·docker·apache·doris·apache doris·轩辕镜像·docker部署doris
广州灵眸科技有限公司12 小时前
xfce桌面触摸校准:基于灵眸科技EASY-EAl-Orin-Nano
数据库·windows·科技
憧憬成为web高手14 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
段一凡-华北理工大学15 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
二宝哥15 小时前
CentOS 7.9 系统下 Redis 5.0.4 单机安装与源码编译安装指南
redis·centos
oradh17 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
z1234567898618 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
程序猿DD18 小时前
一个 API Key,统一调用大模型、生图和联网搜索
数据库·网关
java_logo18 小时前
Docker Compose 部署 ClickHouse:快速搭建高性能列式数据库
数据库·clickhouse·docker·列式数据库·轩辕镜像·高性能数据库·clickhouse部署教程
TlSfoward19 小时前
抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具
数据库·爬虫·网络协议·搜索引擎·php