Redis事务

Redis事务

事务表示的是一组动作,这组动作要么全部执行,要么全部不执行。Redis作为一种高效的分布式数据库,同样支持事务。Redis中的事务(transaction)是一组命令的集合。事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行。

Redis中首先以MULTI开始一个事务,将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面。最后,由EXEC命令触发事务。

下面举例说明,在命令行中输入如下命令。

Redis事务

可以看到,当输入MULTI命令后,服务器返回OK表示事务开始成功,然后依次输入需要在本次事务中执行的所有命令,每次输入一个命令服务器并不会马上执行,而是返回”QUEUED”,这表示命令已经被服务器接受并且暂时保存起来,最后输入EXEC命令后,本次事务中的所有命令才会被依次执行,可以看到最后服务器一次性返回了三个OK,这里返回的结果与发送的命令是按顺序一一对应的,这说明这次事务中的命令全都执行成功了。

接下来,在命令行工具中输入如下命令:

Redis事务

和前面的例子一样,先输入MULTI最后输入EXEC表示中间的命令属于一个事务,不同的是中间输入的命令有一个错误(set写成了sett),这样因为有一个错误的命令导致事务中的其他命令都不执行了(通过后续的get命令可以验证),可见事务中的所有命令都没有得到执行。

上面的例子可以称之为Redis事务语法错误。这种情况需要区分Redis的版本,Redis 2.6.5之前的版本会忽略错误的命令,执行其他正确的命令,2.6.5之后的版本会忽略这个事务中的所有命令,都不执行,就比如上面的例子。

Redis事务中另一类错误称为运行时错误,比如用GET命令获取一个散列表类型的键值。
这种错误在命令执行之前Redis是无法发现的,所以在事务里这样的命令会被Redis接受并执行。如果食物里有一条命令执行错误,其他命令依旧会执行(包括出错之后的命令),下面是一个示例。

Redis事务

如果客户端在发送EXEC命令之前断线了,则服务器会清空事务队列,事务中的所有命令都不会被执行。而一旦客户端发送了EXEC命令之后,事务中的所有命令都会被执行,即使此后客户端断线也没关系,因为服务器已经保存了事务中的所有命令。

除了保证事务中的所有命令要么全执行要么全不执行外,Redis的事务还能保证一个事务中的命令依次执行而不会被其他命令插入。

Watch监控

Watch指令类似乐观锁,事务提交时,如果Key的值已被别的客户端改变,比如某个list已被别的客户端push/pop过了,整个事务队列都不会被执行。

通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败。

Redis事务

上面的例子中,首先设置key的键值为value,然后使用WATCH命令监控key,随后更改key的值为val,然后进入事务,事务中设置key的值为vv,然后执行EXEC运行事务中的命令,最后使用get命令查看key的值,发现key的值还是val,也就是说事务中的命令根本没有执行(因为WATCH监控key的过程中,key被修改了,所以随后的关于key事务便被取消了)。

最后,我们也可以通过UNWATCH 命令,取消 WATCH 命令对所有 key 的监视。