Redis事务,你们真的在用吗

158 阅读5分钟

3iPgq8xxLD.jpg

redis有事务吗?redis的事务是什么呢?和传统的数据库中的事务有什么区别呢 ?不啰嗦,马上开始😂

传统事务简介

  • 是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
  • 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法
  • 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰
  • 传统数据库事务还具有以下特性:
    • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行
    • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束
    • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行
    • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中

上面介绍了传统的数据库事务,那么redis中的事务是什么样子呢,是否也具有acid的特性呢

Redis事务

  • 可以一次执行多个命令,本质是一组命令的集合。
  • 当开启事务时,键入命令,这个时候命令不会真正的被执行,而是放在一个顺序的队列中,只有键入执行命令的时候才会被真正的执行
  • 一个事务中的所有命令都会序列化,按顺序的串行化执行而不会被其他命令插入,不许加塞

与传统数据库事务的区别

  • 单独的隔离操作:Redis的事务仅仅是保证事务里的操作会被连续独占的执行,redis命令的执行是单线程架构,在执行完事务内所有指令前是不可能再去同时执行其他客户端的请求的
  • 没有隔离级别的概念:因为事务在提交前,任何指令都不会被实际的执行,也就不存在 “事务内的查询要看到事务里的更新,在事务外查询不能看到” 这种问题了
  • 不保证原子性:Redis的事务不保证原子性,也就是不能保证所有指令同时成功,或同时失败,只是有决定是否开始执行全部指令的权利,没有执行到一半进行回滚的能力
  • 排他性:Redis会保证一个事务内的命令依次执行,而不会被其他命令插入

Redis事务相关的命令

//取消事务,放弃执行事务块内的所有命令
discard

//执行所有事务块内的命令
exec

//开始一个事务
multi

//监视一个或多个key,如果在事务执行之前,这个key被其他命令所改动,那么事务将被打断
watch key

//取消watch命令对key的监视
unwatch

正常执行一个事务

可以看到,当开始事务之后,键入的每个命令都会放在一个queue里,只有执行了exec命令之后,之前键入的所有命令才会依次执行,那么试想一下,如果执行到中间出错了会怎么样呢?

image.png

放弃事务

image.png

开启事务之后,如果其中有命令出错,那么都不会成功,这里指的是命令的语法错误

image.png

所有的指令语法格式全部正确,那就意味着全部加到了queue中,那么其中的incr k1 因为k1不是数字所以执行到这条指令的时候报错,那么就只有这一条指令失败,其他指令成功执行。有异于关系型数据库的事务。

image.png

实际体验下来 可以发现是有异于关系型数据库的事务,下面介绍一个watch命令

watch监控(类似乐观锁)

  • multi开启事务之前,将要修改的数据监控上,然后开启multi,操作数据。
  • 如果在事务的过程中没有别的线程操作这个监控的数据,那么exec提交事务的时候是成功的,
  • 如果有线程操作了监控的数据,那么exec提交事务就会返回空 失败!
  • 类似乐观锁机制,在提交的时候检查该数据是否被别人动过,如果动过返回失败。
  • 当监控的key自己到时间删除的,提交事务的时候可以提交成功,如果是是自己删除的,那么提交事务的时候不能提交成功
  • 一旦执行了unwatchexec, 之前加的监控锁都会被取消了

总结

  • redis支持事务操作,但是是有异于关系型数据库的事务
  • watch指令,类似乐观锁,事务提交时,如果监控的key的值被修改,整个事务队列都不会执行
  • 通过 watch命令在事务开始之前监控了多个key,那么如果任何一个key被修改 ,事务都不会执行成功,同时返回Nullmulti-bulk应答通知事务执行失败
  • 事务的执行分为三个阶段
    • 开启:multi命令开始一个事务
    • 入队:将多个命令放入一个事务队列中,接到这些命令不会被立即执行,而是放在等待执行的事务队列里
    • 执行:exec命令执行事务

到此 Redis事务就介绍完了,欢迎探讨在项目中的实际使用案例☀️