目录

redis事务

是什么

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

在一个队列中,一次性、顺序性、排他性的执行一系列命令。

怎么用

用法

MULTI 命令用于开启一个事务,它总是返回 OKMULTI 执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中, 当 EXEC命令被调用时, 所有队列中的命令才会被执行。

另一方面, 通过调用 DISCARD , 客户端可以清空事务队列, 并放弃执行事务。

以下是一个事务例子, 它原子地增加了 foobar 两个键的值:

1
2
3
4
5
6
7
8
9
> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1

EXEC 命令的回复是一个数组, 数组中的每个元素都是执行事务中的命令所产生的回复。 其中, 回复元素的先后顺序和命令发送的先后顺序一致。

当客户端处于事务状态时, 所有传入的命令都会返回一个内容为 QUEUED 的状态回复(status reply), 这些被入队的命令将在 EXEC 命令被调用时执行。

常用命令

命令 描述
DISCARD 取消事务,放弃执行事务块内的所有命令。
EXEC 执行所有事务块内的命令。
MULTI 标记一个事务块的开始。
UNWATCH 取消 WATCH 命令对所有 key 的监视。
WATCH key [key …] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

case

正常执行

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200926172315364.png

放弃事务

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200926172419768.png

全体连坐

  • 检测错误的时机:类比java编译异常

  • 发生编译时错误,全体连坐,都不执行

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200926172650981.png

冤头债主

  • 检测错误的时机:类比java运行时异常
  • 发生运行时错误,对的执行,错误的抛出异常

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200926172920871.png

watch监控

  • Watch指令,类似乐观锁,事务提交时,如果Key的值已被别的客户端改变, 整个事务队列都不会被执行
  • 通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化, EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200926180206501.png

上图重新watch无需执行unwatch,因为前面已经执行了exec,一旦执行了exec之前加的监控锁都会被取消掉。

总结

3个阶段

  • 开启:以MULTI开始一个事务
  • 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
  • 执行:由EXEC命令触发事务

3个特性

  • 单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行, 也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题
  • 不保证原子性:部分支持事务,redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。