作者:多米音乐_35692689 | 来源:互联网 | 2023-10-10 13:49
基本概念
Redis事务与其他关系型数据库的事务有很大的区别,Redis事务的本质是一组命令的集合,一次事务的执行实质上就是一组不可被打断、不可被插入的命令的顺序执行,不受其他客户端命令执行的影响。
Redis事务没有隔离级别的概念,所有事务内的操作在事务执行的命令发送前,都被缓存在一个队列中等待,并没有真正的执行,也就不存在事务内的查询看到事务里的更新,事务外查询不能看到事务内的结果。
Redis事务是非原子性的,我们都直到Redis单条命令由于Redis单线程的原因,都是满足原子性的,但是Redis的事务没有增加任何维持原子性的机制,Redis事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
Redis事务
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
序号 | 命令及描述 |
---|
1 | DISCARD 取消事务,放弃执行事务块内的所有命令。 |
2 | EXEC 执行所有事务块内的命令。 |
3 | MULTI 标记一个事务块的开始。 |
4 | UNWATCH 取消 WATCH 命令对所有 key 的监视。 |
5 | WATCH key [key ...] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 |
Redis事务执行失败
这里需要注意的是,某条指令执行失败的含义:
1.命令执行错误,不会回滚事务,除了错误的命令之外其他的命令正常执行
127.0.0.1:6379> SELECT 0
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set num hello
QUEUED
127.0.0.1:6379> incr num
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) ERR value is not an integer or out of range
127.0.0.1:6379> get num
"hello"
127.0.0.1:6379>
2.当Redis事务中出现命令性错误的时候,Redis将放弃该事务,所有处于事务内的操作命令一同放弃
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set num 1
QUEUED
127.0.0.1:6379> incr num
QUEUED
127.0.0.1:6379> dfads
(error) ERR unknown command 'dfads'
127.0.0.1:6379> get num
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>
Watch的使用
根据watch命令的解释,可以理解watch是Redis对于事务执行的线程安全处理
为了防止在事务真正的执行前,其他客户端对事务命令队列中涉及到的key进行操作,造成非线程安全的情况。
在MULTI之前行,使用 WATCH [key] [keys...]对一个或者多个key进行监视,当事务执行过程中,发生了被监视key的操作,当前事务被打断,返回:(nil)。
注意:
- 一但执行 EXEC 开启事务的执行后,无论事务使用执行成功, WARCH 对变量的监控都将被取消。
- 故当事务执行失败后,需重新执行WATCH命令对变量进行监控,并开启新的事务进行操作。
参考:
https://www.cnblogs.com/DeepInThought/p/10720132.html
https://blog.csdn.net/weixin_34198762/article/details/91366875