redis点滴 事务(二)

redis事务 

multi exec discard 和watch 是redis事务的基础

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

 1 事务是一个单独的隔离操作:事务中所有的命令都会序列化,按顺序地执行。事务在执行的过程中,不会被其它来的命令请求打断

 2.事务是一个原子操作:事务中的命令要么全部地执行,要么全部都不执行

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

  1.如果客户端在使用multi 开启一个事务之后,却因为断线而没有成功执行EXEC,那么事务中所有命令都不会执行

  2.另一方面,如果客户端成功在开启事务之后执行EXEC,那么事务中所有命令都会执行

  例如 购票过程,

  ticket-1 ,mobey-100

 而票只有一张,如果在multi之后,跟EXEC之前,被别人买了,所以ticket为0

  那我该如何监视这种情景,并不提交

  悲观的想法:觉得所有的人都在跟我抢这个ticket,此时给ticket上锁,只有我能操作【悲观锁】

  乐观的想法:我只需要注意这个ticket的值就可以了【乐观锁】

 redis的事务中就是开启了乐观锁,只负责监听ticket有没有被改动

 用法

multi 命令用户开启一个事务,它总是返回ok

multi 执行之后,客户端可以继续向服务端发送任意多条命令,这些命令不会立即执行,而是被放到一个队列中,当需要调用时,所有队列中的命令才会被执行

另一方面,通过调用discard,客户端会清除事务队列,并放弃执行事务

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

> MULTI
OK

> INCR foo
QUEUED

> INCR bar
QUEUED

> EXEC
1) (integer) 1
2) (integer) 1

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

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


事务中的错误

使用事务可能会用到下面2种错误

 1.事务在执行exec之前,入列的命令可能会有错,如果说,命令语法错误

  2.命令在调用exec调用之后失败。比如事务命令可能处理了错误类型的键,把列表命令的键放到string中

 对于发生在exec执行之前的错误,客户端的做法是检查命令入列得到的值,如果命令是queue,则入列成功,否则,入列失败,如果入列失败,则大部分事务都会停止并取消这个事务

 对于发生在exec执行之后的错误,并没有对他们进行特别处理:即使事务中某个/某些事务发生错误,而其它的命令仍然会继续执行

 

为什么Redis不支持回滚

如果你有使用关系式数据的经验,那么“redis在事务失败时不进行回滚,而是继续执行余下的命令”这种做法可能会让你觉得有点奇怪

以下是这种做法的优点:

  1.Redis命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中

  2.因为不需要对回滚进行支持,所以Redis的内部保存简单且快速


放弃事务

当执行discard命令时,事务会被放弃,并且客户端会从事务状态中退出


使用check-and-set操作实现乐观锁

watch命令可以为redis事务提供check-and-set(cas)行为

被watch的键会被监视,并会发觉这些键是否被改动。如果至少一个被监视的键在exec执行之前被修改了,那么整个事务都会被取消,exec返回空多条批量回复来表示事务已经失效

举个例子,假设客户端有A和B 2个都读取了键原来的值,比如10,执行incr操作的时候,那么2个客户端都会将键的值设为11,但正确返回结果应该是12才对

有了watch,我们就可以轻松地解决这类问题了:

watch mykey

val=get mykey

val=val+1

multi

set mykey $val

exec

使用上面的代码,如果有了watch之后,exec执行之前,有其他客户端修改了mykey的值,那么当前客户端的事务就会失效。程序需要做的,就是不断重试这个操作,知道没有发生碰撞为止

这种形式的锁被称为乐观锁,它是非常强大的锁机制。并且因为大多数情况下,不同的客户端会访问不同的值,碰撞的情况一般都很少,所以通常并不需要重试













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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值