Redis进阶(二)—— Redis 事务

2. Redis事务

2.1 Redis 事务 和 MySQL 事务区别

Redis 事务 和 MySQL 事务概念上类似,都是指 把一系列操作在一起执行,不允许中间插入。

Redis 事务特点:

  • 弱原子性 或 无原子性:redis 没有回滚机制,只是批量一起执行,里面有失败就是失败了。
  • 不保证一致性:redis 不涉及约束,没有回滚。前后结果不都合理有效,可能有非法中间态。
  • 不需要保隔离性:没有隔离级别,因为不会并发执行事务(redis 单线程处理请求)
  • 不需持久性:存在内存里,是否开启持久,是配置的问题,和事务无关。

Redis 事务本质上,是客户端上有一个 "事务队列",每次客户端开启事务,命令先存到队列中,服务器收到 exec 命令,按顺序执行队列中的操作。

2.2 使用场景示例

Redis 事务,主要就是避免其他客户端命令插队执行,将操作打包执行。

如:秒杀活动

一个经典写法:

bash 复制代码
//获取仓库剩余商品个数
if(个数 > 0) {
	下单成功
	个数减一;	
}

如果不加锁,就存在 "线程安全" 问题,在 Redis 使用事务来解决。

redis 原生命令中不支持类似上面的条件判断,但是 redis 支持 lua 脚本,通过 lua 脚本就可以实现,且和 redis 事务一样是打包批量执行。

2.3 使用事务

redis 中通过 MULTI 开启事务,EXEC 执行事务, DISCARD 放弃当前事务。

开启事务后,先放入事务队列,此时没有执行事务,在其他客户端上是看不到这几个键的。

执行 EXEC

这时,这几个键才真正放入 redis 中,同时在 新窗口中也可查询到。

如果,事务结束前,出现了服务器重启等情况,就相当于是 DISCARD

下面讲一种情况,key 的值初始为 111,客户端1 开启了事务,并将 key 设为 222,但是在客1事务执行前,客户端2 将 key 设为了 333。虽然,从顺序上看,客1 是先设置的 key 为 222,但实际 set key 222 执行的晚,结果为 222。

为此,redis 中有 WATCH 命令可以监视某个或某些 key 在事务执行前是否发生了变化。

客户端1 设置 key1 为 222,但未执行。客户端2 设置 key1 为 .

666。

客户端1 执行事务

由于 key1 在事务执行前发生了改变,所以返回了 nil 没有执行。

2.4 WATCH 的实现原理

watch 的实现,类似于 "乐观锁"。

乐观锁 是一类锁的特质,即加锁前,预期锁冲突几率比较低,先不加锁。冲突真正发生再加锁。

想要看 乐观锁 的更细节讲述,可看此文章:多线程进阶

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

watch key 的时候,会给 key 安排一个 版本号,给 exec 加了一个判定条件,每次修改 key 都会引起版本号变化,当执行 EXEC 时,就会进行判定,版本号不一致说明 key 被修改过,就丢弃该操作,返回 nil;反之,未被修改,进行真正执行。

相关推荐
李广坤1 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
加号33 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏3 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐3 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再3 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
tryCbest3 天前
数据库SQL学习
数据库·sql
jnrjian3 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle
十月南城3 天前
数据湖技术对比——Iceberg、Hudi、Delta的表格格式与维护策略
大数据·数据库·数据仓库·hive·hadoop·spark