当前位置: 首页 > news >正文

[Redis][事务]详细讲解

目录

  • 0.什么是事务?
  • 1.Redis 事务本质
  • 2.Redis 事务意义
  • 3.事务操作
    • 1.MULTI
    • 2.EXEC
    • 3.DISCARD
    • 4.WATCH
    • 5.UNWATCH


0.什么是事务?

  • Redis的事务和MySQL的事务概念上是类似的,都是把一系列操作绑定成一组,让这一组能够批量执行
  • Redis事务和MySQL的区别
    • 弱化的原子性:Redis没有”回滚机制”,只能做到这些操作”批量执行”,不能做到”一个失败就恢复到初始状态”
      • 如果事务中若干个操作,存在有失败的,那就失败吧,不会有回滚操作
    • 不保证一致性:不涉及”约束”,也没有回滚,事务执行过程中如果某个修改操作出现失败,就可能引起不一致的情况
      • MySQL的一致性体现的是运行事务前后运行后,结果都是合理有效的,不会出现中间非法状态
    • 不需要隔离性:也没有隔离级别,因为不会并发执行事务(Redis单线程处理请求)
    • 不需要持久型:是保存在内存的,是否开启持久化,是redis-server自己的事情,和事务无关
  • Redis如果按照集群模式部署,就不支持事务

1.Redis 事务本质

  • Redis事务**本质**上是在服务器上搞了一个”事务队列”,每次客户端在事务中进行一个操作,都会把命令先发给服务器,放到”事务队列”中(但是不会立即执行),而是会在真正收到EXEC命令之后,才真正执行队列中的所有操作
    • 因此,Redis事务的功能相比于MySQL来说,是弱化很多的,只能保证事务中的这几个操作是”连续的”,不会被别的客户端”加塞”,仅此而已
  • 综上
    • Redis事务的意义,就是为了"打包",避免其他客户端的命令,插队到中间
    • 此处的不被插队,不是先抢占位置,而是先让出位置

2.Redis 事务意义

  • Redis的事务为啥就搞的这么简单,为啥不设计成和MySQL一样强大呢?
    • MySQL的事务,在背后付出了很大的代价
      • 空间上,要花费更多的空间来存储更多的数据
      • 时间上,也要有更大的开销
    • 正是因为MySQL有上述的问题,才有了Redis的用武之地
  • 什么时候需要使用到Redis事务呢?
    • 需要把多个操作打包进行,使用Redis事务比较合适
  • 示例:商品抢购
    • 典型写法如果不加上任何限制,就可能会出现线程安全问题
      • 在多线程中,通过加锁的方式,来避免"插队"
      if(count > 0)
      {// 下单成功count--
      }
      
    • 在Redis中直接使用事务即可
      # 开启事务
      get count
      if count > 0decr count
      # 执行事务
      # Redis服务器收到执行事务操作的时候,才会真正执行
      
  • 说明
    • Redis原生命令中不支持条件判定,但是Redis支持lua脚本,可以通过lua实现
    • 可以认为lua脚本的实现方式是Redis事务的进阶版本

3.事务操作

1.MULTI

  • 功能:开启一个事务,执行成功返回OK
  • 当开启事务,并且向服务器发送若干个命令之后,此时服务器重启,此时的这个事务怎么办?
    • 此时的效果相当于DISCARD

2.EXEC

  • 功能:真正执行事务
    • 每次添加一个操作,都会提示”QUEUED”,说明命令已经进入服务端的队列了
    • 真正执行EXEC的时候,服务器才会真正执行命令
  • 示例
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 1
QUEUED
127.0.0.1:6379> set k2 2
QUEUED
127.0.0.1:6379> set k3 3
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) OK127.0.0.1:6379> get k1
"1"
127.0.0.1:6379> get k2
"2"
127.0.0.1:6379> get k3
"3

3.DISCARD

  • 功能:放弃当前事务,此时直接清空事务队列,之前的操作都不会真正执行到
  • 示例
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set k1 1
    QUEUED
    127.0.0.1:6379> set k2 2
    QUEUED
    127.0.0.1:6379> DISCARD
    OK127.0.0.1:6379> get k1
    (nil)
    127.0.0.1:6379> get k2
    (nil)
    

4.WATCH

  • 情景:在执行事务的时候,如果某个事务中修改的值,被别的客户端修改了,此时就容易出现数据不一致的问题
  • 此时key的值是多少呢?
    • 从输入命令的时候看,是客户端1先执行的set key 100,客户端2后执行的set key 200,但是从实际的执行时间看,是客户端2先执行的,客户端1后执行的
      # 客⼾端 1 先执⾏
      127.0.0.1:6379> MULTI
      OK
      127.0.0.1:6379> set key 100
      QUEUED# 客⼾端 2 再执⾏
      127.0.0.1:6379> set key 200
      OK# 客⼾端 1 最后执⾏
      127.0.0.1:6379> EXEC
      1) OK# 结果查询
      127.0.0.1:6379> get key
      "100"
      
    • 这个时候,其实很容易引起歧义
    • 因此,即使不保证严格的隔离性,至少也要告诉用户,当前的操作可能存在风险
  • watch命令就是用来解决这个问题的,watch在该客户端上监控一组具体的key
    • 当开启事务的时候,如果对watchkey进行修改,就会记录当前key的”版本号”
    • 在真正提交事务的时候,如果发现当前服务器上的key的版本号已经超过了事务开始时的版本号,就会让事务执行失败
  • watch本质上是给exec加了个判定条件,属于"乐观锁"
  • 示例
    # 客户端1先执行
    127.0.0.1:6379> watch k1        
    OK
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set k1 100      
    QUEUED
    127.0.0.1:6379> set k2 1000     
    QUEUED
    # 只是入队列,但是不提交事务执行# 客户端2后执行
    127.0.0.1:6379> set k1 200     
    OK# 客户端1再执行
    127.0.0.1:6379> EXEC          
    (nil)
    127.0.0.1:6379> get k1
    "200"
    127.0.0.1:6379> get k2
    (nil)
    # 此时说明事务已经被取消了,这次提交的所有命令都没有执行
    

5.UNWATCH

  • 功能:取消对key的监控,相当于WATCH的逆操作
http://www.lryc.cn/news/447449.html

相关文章:

  • Latex——一行的划线 如何分开
  • 大数据:快速入门Scala+Flink
  • 侧边菜单的展开和折叠
  • 自动化办公-Python中的for循环
  • Python_itertools
  • Apache Iceberg 数据类型参考表
  • 职责链模式
  • 新品 | Teledyne FLIR IIS 推出Forge 1GigE SWIR 短波红外工业相机系列
  • 深入MySQL:掌握索引、事务、视图、存储过程与性能优化
  • 【WSL——Windows 上使用 Linux 环境】
  • Redis:事务
  • 策略模式的介绍和具体实现
  • MySQL InnoDB MVCC数据结构分析
  • MySQL 8 查看 SQL 语句的执行进度
  • OpenStack 部署实践与原理解析 - Ubuntu 22.04 部署 (DevStack)
  • 【软件工程】可行性研究
  • 乌克兰因安全风险首次禁用Telegram
  • [SDX35]SDX35如何查看GPIO的Base值
  • 【Linux学习】【Ubuntu入门】2-1-1 vim编辑器设置
  • 全栈开发(一):springBoot3+mysql初始化
  • 有关若依登录过程前端的对应处理学习
  • django使用笔记6--docker部署
  • 高性能、高可靠,MK SD卡让数据存储无忧!
  • NetAssist测试TCP和UDP
  • mcuboot使用介绍
  • 如何在 Linux 终端使用 GET 和 POST 请求
  • 主从数据库同步配置详解(MySQL/MariaDB)
  • 台式机通过笔记本上网
  • golang雪花算法实现64位的ID
  • LeetCode 137. 只出现一次的数字 II