Reddis(14)事务

事务

事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

注意:单条命令保证原子性,整个事务操作不保证原子性。

MULTI 、 EXEC 、 DISCARD 事务命令

MULTI 命令用于开启一个事务:

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

EXEC 命令负责触发并执行事务中的所有命令:

  • 如果客户端在使用 MULTI 开启了一个事务之后,却因为断线而没有成功执行 EXEC ,那么事务中的所有命令都不会被执行。
  • 另一方面,如果客户端成功在开启事务之后执行 EXEC ,那么事务中的所有命令都会被执行
127.0.0.1:6379> mset k1 v1 k2 v2 
QUEUED
127.0.0.1:6379> mget k1  k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) 1) "v1"
   2) "v2"

DISCARD 命令的调用 , 客户端可以清空事务队列, 并放弃执行事务.

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k4 v4 
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> mget k1 k4 
1) "v1"
2) (nil) 

事务的错误

使用事务时可能会遇上以下两种错误:

  • 事务在执行 EXEC 之前,入队的命令可能会出错。比如说,命令可能会产生语法错误(参数数量错误,参数名错误,等等),或者其他更严重的错误,比如内存不足(如果服务器使用 maxmemory 设置了最大内存限制的话)。
  • 命令可能在 EXEC 调用之后失败。举个例子,事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面,

上述两种类似于java种的编译错误与运行时错误。
前者 全部命令失败,后者,除了出错命令失败,其他命令成功,不能保证事务的原子性。


127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1 k2 v2
QUEUED
127.0.0.1:6379> get k1 k2
(error) ERR wrong number of arguments for 'get' command
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec #失败
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key1 aaa
QUEUED
127.0.0.1:6379> get key1
QUEUED
127.0.0.1:6379> incr key1 
QUEUED
127.0.0.1:6379> exec #成功,但是出错命令失败,
1) OK
2) "aaa"
3) (error) ERR value is not an integer or out of range

redis的乐观锁

watch 监控一个元素,相当于version.

乐观锁成功

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> WATCH money #添加监控
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> DECRBY money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec 
1) (integer) 80
2) (integer) 20

执行事务比较moneny的值是否改变,没改变成功。执行成功后,watch自动失效。

乐观锁失败

事务未执行exec操作时。

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED

另外一个用户进行修改了money的值

127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 100
OK

然后再执行exec操作,失败。

127.0.0.1:6379> exec
(nil)

执行事务比较moneny的值是否改变,改变了失败。

事务失败,watch没有解除监控,要想成功,首先解除监控,然后绑定监控,再进行书屋操作

127.0.0.1:6379> unwatch
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
127.0.0.1:6379> exec
1) (integer) 90
2) (integer) 30

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值