玖叶教程网

前端编程开发入门

一篇图文,搞定Redis事务

在面试的时候,通常会被问到redis是如何实现分布式锁的。如果我们只知道是借助于setnx/setex ,而不了解setnx/setex底层如何实现,那基本上是无法过关的,尤其是大厂。那究竟redis是怎么实现事务的呢?

1、redis事务的用法

redis支持事务操作。它的实现依赖于multi 和exec 关键字。其中,multi表示事务开启,exec表示执行multi到exec之间的语句块。系统检测multi 语句后,会将其后的命令添加到命令队列中去,直到遇到exec时,才一并执行,不会被中断。具体使用如图所示:

注意: 在multi开启的事务中,如果其它线程也修改了该key的值,那么,multi事务依旧会被执行,且multi中设定的该key的值会覆盖掉其它线程设定的值。如下图所示:

在左图事务还没有提交的时候,右图的另一个事务修改的key的值,这个时候,修改后的值,会在事务的get key命令中体现出来。然后由于在左图的事务中又执行了set name操作,导致事务执行成功后此前设置的name值被修改。

2、watch关键字在redis事务的作用

要解决这个问题,就必须在事务开启前,添加watch关键字,对一个或多个待更新的key进行监视。一旦key的值被其他线程所修改,则事务将停止执行watch关键字的本质是一个乐观锁。如下图所示:

在左图中,利用watch关键字监听了name 和 age这两个key, 接着用multi关键字开启事务。但是在执行exec之前,右图中所示线程修改了name的值。可以看到,exec事务执行的返回结果是nil. name的值为jacy

那如果只监听一个key呢?那事务是否可以正常执行?

答案是否!!

测试如下:

从图中可以清楚看到,只要事务中被监听的key被其它线程修改,那整个事务都将不会被执行。原因是服务端在监听到key被修改的事件后,便执行了discard命令,它会丢弃掉该事务中的所有语句块和watch的关键字。

3、事务执行的过程中,有语句执行失败怎么办?

在redis事务语句块中,如果有部分语句执行失败,那也不影响其它的语句执行。如下图所示:

从中可以看出,事务中的第2条语句(尝试对一个字符串类型的value 执行加1操作时)失败,但是语句块中的其它语句都执行成功并生效了。

为什么事务中有语句执行失败不会回滚呢??

这是因为在作者看来,事务执行失败大多是程序的问题,而且这样的问题大多在开发和测试环境中就已经会暴露并解决了,生产上不可能出现这样的问题。而且,事务回滚与作者“简单方便高效”的设计初衷相违背。因此作者就不支持事务执行失败情况下的回滚。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言