Redis事务

Redis事务

redis事务简介

redis事务的本质:

  • 一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,都会被顺序执行
  • redis事务特性:一次性,顺序性,排他性(事务在执行期间不会被主动中断,执行完事务中的所有命令之后才会继续处理其他客户端的其他命令)
  • redis事务中没有隔离性
  • 事务中的命令只有在exec后才开始执行

redis单条命令是保证原子性的,但是redis的事务是不保证原子性的

示例:

// 开启事务
multi
// 开启事务后,所有命令依次入队
set k v
set k1 v2
// 执行事务,命令队列中的命令才会依次执行
exec
// 放弃事务,事务队列中的命令都被清空
discard

如果事务中存在编译时异常,比如我在入队时添加了redis根本没有的命令,那么直接就会抛出异常不会等到exec,事务中的其他命令不会被执行

在这里插入图片描述

如果事务队列中某些命令存在运行时异常,那么在exec时,其他命令可以正常执行,错误命令抛出异常,比如我对字符串的value进行自增,那么该命令就会报错,但是其他命令正常执行

在这里插入图片描述

事务原理

当开启事务时,即执行multi,redis会由非事务状态转为事务状态,那redis服务器在接收到命令时就会将命令放在事务队列中,等待exec,并不是所有的命令都会被放进事务队列, 其中的例外就是 EXECDISCARDMULTIWATCH 这四个命令 —— 当这四个命令从客户端发送到服务器时, 它们会像客户端处于非事务状态一样, 直接被服务器执行:

在这里插入图片描述

如果客户端正处于事务状态, 那么当 EXEC 命令执行时, 服务器根据客户端所保存的事务队列, 以先进先出(FIFO)的方式执行事务队列中的命令: 最先入队的命令最先执行, 而最后入队的命令最后执行。

Redis 的事务是不可嵌套的, 当客户端已经处于事务状态, 而客户端又再向服务器发送 MULTI 时, 服务器只是简单地向客户端发送一个错误, 然后继续等待其他命令的入队。 MULTI 命令的发送不会造成整个事务失败, 也不会修改事务队列中已有的数据。(保证排他性

redis watch机制

watch命令用来在事务开始之前监控任意数量的key,当调用exec时,如果被监控的key被其他redis客户端修改,那么整个事务不会被执行,直接返回失败

在这里插入图片描述

实现原理

在redis每个数据库中都有一个watch_keys的字典,字典的键就是这个数据库被监视的键,而字典的值就是一个链表, 链表中保存了所有监视这个键的客户端

在这里插入图片描述

执行watch命令就是将客户端实例添加到watch_keys的指定链表中

如果程序想检查某个键是否被监视, 那么它只要检查字典中是否存在这个键即可; 如果程序要获取监视某个键的所有客户端, 那么只要取出键的值(一个链表), 然后对链表进行遍历即可

watch触发

在所有对数据库的key修改命令执行后, multi.c/touchWatchedKey 函数都会被调用 —— 它检查数据库的 watched_keys 字典, 看是否有客户端在监视已经被命令修改的键, 如果有的话, 程序将所有监视这个/这些被修改键的客户端的 REDIS_DIRTY_CAS 选项打开,当客户端发送exec命令触发事务执行,服务器会对该客户端的状态进行检查,如果客户端的 REDIS_DIRTY_CAS 选项已经被打开,那么说明被客户端监视的键至少有一个已经被修改了,事务的安全性已经被破坏,则事务失败

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值