Redis的事务

Redis事务

是什么?

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

能做什么?

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

常用命令

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

如何用?

正常执行

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set id 1
QUEUED
127.0.0.1:6379> get id
QUEUED
127.0.0.1:6379> INCR id
QUEUED
127.0.0.1:6379> INCR id
QUEUED
127.0.0.1:6379> get id
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "1"
3) (integer) 2
4) (integer) 3
5) "3"
127.0.0.1:6379> 

放弃事务

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set id 1
QUEUED
127.0.0.1:6379> set name z3
QUEUED
127.0.0.1:6379> set age 23
QUEUED
127.0.0.1:6379> INCR id
QUEUED
127.0.0.1:6379> DISCARD
OK

全体连坐
对于语句错误,所有语句都不会成功

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set name 1
QUEUED
127.0.0.1:6379> sdsad
(error) ERR unknown command 'sdsad'
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

冤有头债有主
在exec时发现的错误,不会全体失败,成功的语句会正常执行。

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set age 1
QUEUED
127.0.0.1:6379> INCR age
QUEUED
127.0.0.1:6379> set name z3
QUEUED
127.0.0.1:6379> INCR name.      #name为字符串,自增会出现错误
QUEUED
127.0.0.1:6379> get age
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (integer) 2
3) OK
4) (error) ERR value is not an integer or out of range
5) "2"

Watch监控

watch指令,类似乐观锁,如果key值已经被修改了,那么整个事务队列都不会执行,同时返回一个Nullmulti-bulk应答以通知调用者事务执行失败。

注意:一旦执行了exec或者discard,之前加的所有监控锁都会被取消掉。

案例:

  • 初始化信用卡可可用额度和欠费额度
127.0.0.1:6379> set balance 100
OK
127.0.0.1:6379> set debt 0
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY balance 20
QUEUED
127.0.0.1:6379> INCRBY debt 20
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 80
2) (integer) 20
  • 无加塞篡改
127.0.0.1:6379> WATCH balance
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY balance 10
QUEUED
127.0.0.1:6379> INCRBY debt 10
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 70
2) (integer) 30
  • 有加塞篡改
127.0.0.1:6379> WATCH balance
OK
127.0.0.1:6379> set balance 666
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY balance 10
QUEUED
127.0.0.1:6379> INCRBY debt 10
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get balance
"666"
127.0.0.1:6379> get debt
"30"
  • 使用unwatch
127.0.0.1:6379> WATCH balance
OK
127.0.0.1:6379> set balance 100
OK
127.0.0.1:6379> UNWATCH
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set balance 50
QUEUED
127.0.0.1:6379> set debt 0
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
127.0.0.1:6379> get balance
"50"
127.0.0.1:6379> get debt
"0"

3阶段

开启:使用multi开启事务

入队:将多个命令入队到事务中,接到这些命令不会立即执行,而是放到等待执行的事务队列里面。

执行:有exec命令出发事务

3特性

单独的隔离操作:事务中的所有命令都会序列化,按顺序的执行。事务在等待执行的时候,不会被其他客户端发送来的米命令请求打断

没有隔离级别的概念:队列中的所有命令没有提交exec之前都是不会被执行的

不保证原子性:redis中如果一条命令执行失败,其后的命令仍然会被执行,没有回滚。

posted @ 2020-09-21 14:56  HankinkK  阅读(106)  评论(0)    收藏  举报