谈到事务我们先来回顾一下传统数据库的事务 : 在一次与数据库连接的会话中 , 所有执行的 SQL 要么一起成功 ,要么一起失败 .
既然有传统数据库的事务,那么为啥 redis 会把事务单独拿出来 称 redis 事务呢 ?
下面我们就怀着 几个问题来学习一下我们的 redis 事务 .
官网 : https://redis.io/docs/manual/transactions/
redis 事务 : 可以一次执行多个命令 ,本质是一组命令的集合 。 一个事务中 所有命令都会被序列化 . 按顺序串行化执行而不会其他命令插入,不许加塞
使用 redis 事务 能 在一个队列中 ,一次性,顺序性,排他性的执行一系列的命令。
Redis事务 VS 数据库事务
单独的隔离操作 : Redis 的事务仅仅是保证事务里的操作会被连续独占的执行 , redis 命令执行是单线程架构 ,
在执行完事务内所有指令前是不可能在去同时执行其他客户端的请求的
没有隔离级别的概念 : 因为事务提交前任何指令都不会执行 , 也就不存在 “事务内的查询要看到事务的更新”
在事务外查询能看到这个问题了.
不保证原子性 : Redis的事务 不保证原子性
, 也就是不能保证所有指令同时成功 或 同时失败 , 只有决定是否
开始执行全部指令的能力,没有执行到一半进行回滚的能力.
排他性 :Redis 会保证一个事务内的命令依次执行,而不会被其他命令插入
相关命令 :
命令 | 功能 |
---|---|
discard | 取消事务 ,放弃执行事务块内的所有代码 |
exec | 执行所有事务快内的命令 |
multi | 标记一个事务块的开始 |
unwatch | 取消 watch 命令对所有key 的监视 |
watch key [key …] | 监视一个 或 多个 key , 如果事务执行 之前这个(或这些) key 被其他命令所改动,那么事务将被打断 |
使用到的命令 : multi 开启事务 , exec 执行事务
代码演示 :
使用到的命令 : multi 开启事务 , discard 取消事务
代码演示 :
全体连坐 : 就是 开始事务后 ,写了一个 错误的命令 ,然后执行 , 因为这个错误导致所有命令全部失效.
官网 :
代码演示 :
官网 :
冤头债主 : 简单来说 就是 在事务中 ,执行某个命令错误 ,不会影响 其他命令 ,导致整个事务取消 . 谁错误就找谁 .
代码演示 :
关于案例三 和 案例四 , 就有点像 java 的 编译时异常 和 运行时异常 .
出现 全体连坐 一般是 语法错误造成的 , 而冤头债主 一般是 运行时异常.
在 redis 中 使用 watch 来提供乐观锁定 , 类似于 CAS (Check - and - Set) .
简单复习一下 :
悲观锁
悲观锁 顾名思义 ,就是很悲观 ,每次去拿数据的时候都认为别人会修改 ,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁.
乐观锁
乐观锁 顾名思义 ,就是很乐观 ,每次去拿数据的时候都认为别人不会修改 , 所以不会上锁 , 但是更新的时候会判断一下在此期间 别人有没有去更新这个数据 .
乐观锁策略 : 提交版本必须 大于 记录当前版本才能执行更新
CAS :
使用 watch 监视一个 key ,如果 key 在监控期间 被人修改了,那么本次事务操作会返回一个 null , 也就是 这个事务被人打断了 需要重新执行.
图一 :
图二 :
补充 :
exec
之前加的监视都会被取消掉了
所谓 redis 事务就 三步操作 :
multi
开始一个事务exec
命令触发事务