尚硅谷redis7 47-48 redis事务之理论简介

47 redis事务之理论简介

什么是事务

可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入

能干什么?

一个队列中,一次性、顺序性、排他性的执行一系列操作

redis事务vs数据库事务

1 单独的隔离操作

Redis的事务仅仅是保证事务里的操作会被连续独占的执行,++redis命令执行是单线程架构++,在执行完事务内所有指令前是不可能再去同时执行其他客户端的请求的

2 没有隔离级别的概念

因为事务提交前任何指令都不会被实际执行【只是放在队列里面不会执行】,也就不存在"事务内的查询要看到事务里的更新,在事务外查询不能看到"这种问题了

3不保证原子性

Redis的事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半进行回滚的能力

4 排它性

Redis会保证一个事务内的命令依次执行,而不会被其它命令插入

48 redis事务之案例实操

Redis 事务是通过 MULTI 命令进入的。该命令始终返回 OK。此时,用户可以发送多个命令,但 Redis 不会立即执行这些命令,而是将它们排入队列中。所有命令会在调用 EXEC 命令后一次性执行。

如果调用 DISCARD 命令,则会清空事务队列并退出事务

redis事务命令

1.DISCARD 取消事务→放弃执行事务块内的所有命令。

2.EXEC 执行所有事务块内的参令。

3.MULTI 标记一个事务块的开始。

4.UNWATCH 取消WATCH 命令对所有key的监视,

5.WATCH key [key .. ] 监视一个(或多个)key,如果在事劳执行之前这个(或这些)key被其他命令所改动,那么事务将被打断。

CASE1:正常执行

MULTI 和 EXEC

CASE2:放弃事务

MULTI 和 DISCARD

CASE3:全体连坐

一条命令出错,就全部放弃执行

127.0. 0.1:6379> MULTI

OK

      1. 1: 6379(TX)> set k1 v111

QUEUED

127.0. 0. 1: 6379( TX)> set k2 v222

QUEUED

127.0.0.1:6379(TX)> set k3 // 这个命令本身就是错误的

(error) ERR wrong number of arguments for 'set' command

      1. 1: 6379( TX) >
      1. 1: 6379( TX) > EXEC

EXECABORT Transaction discarded because of previous errors. //事务队列中的所有命令都不执行

事务中的错误

在事务过程中,可能会遇到两类命令错误:

  1. 命令在排队阶段失败 :也就是说,在调用 EXEC 之前就发生了错误。例如,命令可能存在语法错误(参数数量错误、命令名称错误等),或者遇到某些关键问题,如内存不足(例如服务器配置了 maxmemory 指令设置了内存上限)。

    1. 这种情况只能全部命令都放弃执行
  2. 命令在 EXEC 后执行时失败:例如,对某个键执行了不适用的操作(比如对一个字符串类型的键执行列表操作)。

CASE4:冤头债主

在执行 EXEC 之后发生的错误不会被特殊处理:即使事务中的某个命令执行失败,其他命令仍然会被继续执行。

总结:对的放行,错的不执行

补充:redis不提供事务回滚的功能,开发者必须在事务执行出错后,自行恢复数据库状态。

INCR email命令错误:邮箱是字符串不可能自增

CASE5:watch监控

redis的watch类似于乐观锁的设定,类似于CAS

悲观锁是一种假设"总会发生冲突"的锁机制。假设每次访问数据都是对数据进行修改。因此在对数据进行操作前,会先加锁,防止其他线程同时访问,以确保数据安全。

乐观锁假设"并发冲突是少数",所以**不加锁。**假设每次访问数据都不会修改数据。因此在更新数据时才校验数据是否被其他线程修改。

CAS 是一种无锁的原子操作,全称是 比较并交换。它是乐观锁的具体实现方式之一,底层依赖于 CPU 的原子指令。

工作原理:

  • 先读取变量的旧值

  • 和预期值进行比较

  • 如果相等,则更新为新值

  • 如果不等,说明有其他线程修改过,则重试或失败

watch

初始化k1和balance两个key,先监控再开启multi,保证两key变动在同一个事务内

      1. 1:6379> set k1 abc

OK

      1. 1: 6379> set balance 100

OK

      1. 1:6379>
      1. 1: 6379> WATCH balance

OK

127.0. 0.1:6379>

      1. 1: 6379> MULTI

OK

      1. 1: 6379( TX) > set k1 abc2

QUEUED

      1. 1: 6379( TX) > set balance 110

QUEUED

      1. 1: 6379( TX) > EXEC
  1. OK

  2. OK

127.0. 0. 1:6379> get k1

"abc2"

有加塞篡改:

客户端1监控了balance

客户端2修改了balance

客户端1的事务执行失败返回空

unwatch

UNWATCH 用于 取消之前通过 WATCH 命令监视的所有键,避免这些键的变动影响事务的执行。

  • 在你使用 WATCH 命令监控某些键的变化时,如果你不再想基于这些键判断是否执行事务 ,就可以用 UNWATCH 来取消。

  • 如果你调用了 DISCARD,Redis 会自动 UNWATCH,无需手动取消。

WATCH mykey

GET mykey

UNWATCH # 取消监视

MULTI

SET mykey "newvalue"

EXEC

小结

一旦执行了exec之前加的监控锁都会被去掉。

当客户端连接丢失【比如退出连接】,所有东西都会被取消监视

相关推荐
seabirdssss几秒前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续9 分钟前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben04411 分钟前
ReAct模式解读
java·ai
xhbh66626 分钟前
开发效率翻倍:资深DBA都在用的MySQL客户端利器
数据库·mysql·数据库连接工具·mysql 连接工具
LJC_Superman40 分钟前
Web与Nginx网站服务
运维·服务器·前端·网络·数据库·nginx·vim
java水泥工44 分钟前
校园管理系统|基于SpringBoot和Vue的校园管理系统(源码+数据库+文档)
数据库·vue.js·spring boot
轮到我狗叫了1 小时前
牛客.小红的子串牛客.kotori和抽卡牛客.循环汉诺塔牛客.ruby和薯条
java·开发语言·算法
高山有多高1 小时前
详解文件操作
c语言·开发语言·数据库·c++·算法
盒马coding1 小时前
PostgreSQL与Greenplum常见连接客户端
数据库·postgresql
言之。1 小时前
Django get_or_create 方法详解
数据库·django·sqlite