redis事务


 

1. 前言

 

谈到事务我们先来回顾一下传统数据库的事务 : 在一次与数据库连接的会话中 , 所有执行的 SQL 要么一起成功 ,要么一起失败 .

 
既然有传统数据库的事务,那么为啥 redis 会把事务单独拿出来 称 redis 事务呢 ?

 
下面我们就怀着 几个问题来学习一下我们的 redis 事务 .

  1. redis事务是什么?
  2. redis 事务与 传统数据库的事务具有那些区别?

 

2. redis 事务

 

官网 : https://redis.io/docs/manual/transactions/

在这里插入图片描述

 

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

 
使用 redis 事务 能 在一个队列中 ,一次性,顺序性,排他性的执行一系列的命令。

 
Redis事务 VS 数据库事务

  1. 单独的隔离操作 : Redis 的事务仅仅是保证事务里的操作会被连续独占的执行 , redis 命令执行是单线程架构 ,

    在执行完事务内所有指令前是不可能在去同时执行其他客户端的请求的

  2. 没有隔离级别的概念 : 因为事务提交前任何指令都不会执行 , 也就不存在 “事务内的查询要看到事务的更新”

    在事务外查询能看到这个问题了.

  3. 不保证原子性 : Redis的事务 不保证原子性 , 也就是不能保证所有指令同时成功 或 同时失败 , 只有决定是否

    开始执行全部指令的能力,没有执行到一半进行回滚的能力.

  4. 排他性 :Redis 会保证一个事务内的命令依次执行,而不会被其他命令插入

 

3. Redis 事务使用

 
相关命令 :

命令 功能
discard 取消事务 ,放弃执行事务块内的所有代码
exec 执行所有事务快内的命令
multi 标记一个事务块的开始
unwatch 取消 watch 命令对所有key 的监视
watch key [key …] 监视一个 或 多个 key , 如果事务执行 之前这个(或这些) key
被其他命令所改动,那么事务将被打断

 

3.1 案例一 : 正常执行

 
使用到的命令 : multi 开启事务 , exec 执行事务

 
代码演示 :

在这里插入图片描述

 

3.2 案例二 : 放弃执行

 
使用到的命令 : multi 开启事务 , discard 取消事务

 
代码演示 :

在这里插入图片描述

 

3.3 案例三 : 全体连坐

 

全体连坐 : 就是 开始事务后 ,写了一个 错误的命令 ,然后执行 , 因为这个错误导致所有命令全部失效.

 
官网 :

在这里插入图片描述

 
代码演示 :

在这里插入图片描述

 

3.4 案例四 : 冤头债主

 
官网 :

在这里插入图片描述

 
冤头债主 : 简单来说 就是 在事务中 ,执行某个命令错误 ,不会影响 其他命令 ,导致整个事务取消 . 谁错误就找谁 .

 
代码演示 :

在这里插入图片描述

 
关于案例三 和 案例四 , 就有点像 java 的 编译时异常 和 运行时异常 .
 
出现 全体连坐 一般是 语法错误造成的 , 而冤头债主 一般是 运行时异常.

 

3.5 案例五 : watch 监控

 
在 redis 中 使用 watch 来提供乐观锁定 , 类似于 CAS (Check - and - Set) .

 
简单复习一下 :

 
悲观锁

 
悲观锁 顾名思义 ,就是很悲观 ,每次去拿数据的时候都认为别人会修改 ,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁.

 
乐观锁

 
乐观锁 顾名思义 ,就是很乐观 ,每次去拿数据的时候都认为别人不会修改 , 所以不会上锁 , 但是更新的时候会判断一下在此期间 别人有没有去更新这个数据 .

 
乐观锁策略 : 提交版本必须 大于 记录当前版本才能执行更新

 
CAS :

在这里插入图片描述

 
使用 watch 监视一个 key ,如果 key 在监控期间 被人修改了,那么本次事务操作会返回一个 null , 也就是 这个事务被人打断了 需要重新执行.

 
图一 :

在这里插入图片描述

 
图二 :

在这里插入图片描述

 
补充 :

  1. 一旦执行了 exec 之前加的监视都会被取消掉了
  2. 当客户端连接丢失的时候 (比如 退出连接) ,所有东西都会被取消监视.

 

4. 总结

 

所谓 redis 事务就 三步操作 :

  1. 开启 : 以 multi 开始一个事务
  2. 入队 : 将多个命令入队到事务中 , 接到这些命令并不会立刻执行 , 而是放到等待执行的事务队列里面.
  3. 执行 : 由 exec 命令触发事务