快速了解 Redis 事务

1.相关指令

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

  1. multi
  • 开启事务
java 复制代码
multi
  1. exec
  • 执行事务
java 复制代码
exec
  1. discard
java 复制代码
discard

2.Redis 事务的特性

Redis 的事务与 MySQL 事务有很大的区别。

  1. 不保证原子性:Redis 没有"回滚机制",只能做到这些操作"批量执行"。不能做到"⼀个失败就恢复到初始状态"。
  • Redis 初始时没有数据
  1. 不需要隔离性:事务中的所有命令都会按顺序执行(注意是执行,要 exec 后),不会被其他客户端的命令打断(Redis 是单线程执行请求的)。

  2. 不需要持久性:Redis 是保存在内存的。是否开启持久化要看配置,和事务⽆关。

  3. 不保证⼀致性:MySQL 的⼀致性体现的是运⾏事务前运⾏后,结果都是合理有效的,不会出现中间⾮法状态。而 Redis 事务,有可能出现数据不一致的情况。

  • 客户端1:
java 复制代码
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set key1 200
QUEUED
  • 客户端2:
java 复制代码
127.0.0.1:6379> set key1 100
OK
  • 客户端1:
java 复制代码
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set key1 200
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
127.0.0.1:6379> 
  • 客户端2:
java 复制代码
127.0.0.1:6379> set key1 100
OK
127.0.0.1:6379> get key1
"200"
127.0.0.1:6379> 

可以看到,在没有提交事务前,如果有其它客户端修改事务中相关的数据,可能让造成其它客户端的更新丢失了。比如上面案例的客户端2,如何解决呢?可以通过搭配 watch 指令来完成。

3.watch 指令

  1. 当开启事务的时候,如果对 watch 的 key 进⾏修改,就会记录当前 key 的"版本号"。(版本号是个简单的整数,每次修改都会使版本变⼤)
  2. 在真正提交事务的时候,如果发现当前服务器上的 key 的版本号已经超过了事务开始时的版本号,就会让对应的 key 执⾏失败,但是没有被 watch 监控的 key 还是会被执行。
  • 客户端1:
java 复制代码
127.0.0.1:6379> watch key
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set key 100
QUEUED
127.0.0.1:6379(TX)> set key1 200
QUEUED
127.0.0.1:6379(TX)> 
  • 客户端2:
java 复制代码
127.0.0.1:6379> set key 20
OK
127.0.0.1:6379> 
  • 客户端1:
java 复制代码
127.0.0.1:6379> watch key
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set key 100
QUEUED
127.0.0.1:6379(TX)> set key1 200
QUEUED
127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379> get key
"20"
127.0.0.1:6379> get key1
"200"
127.0.0.1:6379> 
  • 客户端2:
java 复制代码
127.0.0.1:6379> set key 20
OK
127.0.0.1:6379> get key
"20"
127.0.0.1:6379>

注意到,并没有停止执行事务。没有被 watch 监控的 key 还是会被执行。

相关推荐
幼稚园的山代王18 小时前
go语言了解
开发语言·后端·golang
kkjt013018 小时前
{MySQL查询性能优化索引失效的八大场景与深度解决方案}
后端
ss27319 小时前
手写MyBatis第107弹:@MapperScan原理与SqlSessionTemplate线程安全机制
java·开发语言·后端·mybatis
橙子家19 小时前
log4net 简介以及简单示例(.net8)
后端
间彧20 小时前
Spring Boot分布式WebSocket实现指南:项目实战与代码详解
后端
间彧20 小时前
Spring Boot集成WebSocket项目实战详解
后端
非凡的世界21 小时前
Thinkphp8 Redis队列与消息队列topthink/think-queue 原创
数据库·redis·bootstrap·thinkphp
该用户已不存在21 小时前
工具用得好,Python写得妙,9个效率工具你值得拥有
后端·python·编程语言
zym大哥大1 天前
C++客服端访问redis
数据库·redis·缓存
im_AMBER1 天前
Web 开发 30
前端·笔记·后端·学习·web