Redis事务深入解析和使用

作为关系型数据库中一项非常重要的基础功能——事务,在 Redis 中是如何处理并使用的?

1.前言

事务指的是提供一种将多个命令打包,一次性按顺序地执行的机制,并且保证服务器只有在执行完事务中的所有命令后,才会继续处理此客户端的其他命令。
事务也是其他关系型数据库,所必备的一项非常重要的能力。以支付的场景为例,正常情况下只有正常消费完成之后,才会减去账户余额。但如果没有事务的保障,可能会发生消费失败了,但依旧会把账户的余额给扣减了,我想这种情况应该任何人都无法接受吧?所以事务是关系型数据库中一项非常重要的基础功能。

2.事务基本使用

事务在其他语言中一般执行过程分为三个阶段:

开启事务——Begin Transaction

执行业务代码,提交事务——Common Transaction

业务处理中出现异常,回滚事务——Rollback Transaction

以 Java 中的事务执行为例:

// 开启事务 begin(); try { //...... // 提交事务 commit(); } catch(Exception e) { // 回滚事务 rollback(); }

Redis 中的事务从开始到结束也是要经历三个阶段:

开启事务

命令入列

执行事务/放弃事务

其中,开启事务使用 multi 命令,事务执行使用 exec 命令,放弃事务使用 discard 命令。

1)开启事务

multi 命令用于开启事务,实现代码如下:

> multi OK

multi 命令可以让客户端从非事务模式状态,变为事务模式状态,如下图所示:

image.png


注意:multi 命令不能嵌套使用,如果已经开启了事务的情况下,再执行 multi 命令,会提示如下错误:

(error) ERR MULTI calls can not be nested

执行效果,如下代码所示:

127.0.0.1:6379> multi OK 127.0.0.1:6379> multi (error) ERR MULTI calls can not be nested

当客户端是非事务状态时,使用 multi 命令,客户端会返回结果 OK ,如果客户端已经是事务状态,再执行 multi 命令会 multi 命令不能嵌套的错误,但不会终止客户端为事务的状态,如下图所示:

image.png

2)命令入列

客户端进入事务状态之后,执行的所有常规 Redis 操作命令(非触发事务执行或放弃和导致入列异常的命令)会依次入列,命令入列成功后会返回 QUEUED ,如下代码所示:

> multi OK > set k v QUEUED > get k QUEUED

执行流程如下图所示:

image.png


注意:命令会按照先进先出(FIFO)的顺序出入列,也就是说事务会按照命令的入列顺序,从前往后依次执行。

3)执行事务/放弃事务

执行事务的命令是 exec ,放弃事务的命令是 discard 。
执行事务示例代码如下:

> multi OK > set k v2 QUEUED > exec 1) OK > get k "v2"

放弃事务示例代码如下:

> multi OK > set k v3 QUEUED > discard OK > get k "v2"

执行流程如下图所示:

image.png

3.事务错误&回滚

事务执行中的错误分为以下三类:

执行时才会出现的错误(简称:执行时错误);

入列时错误,不会终止整个事务;

入列时错误,会终止整个事务。

1)执行时错误 示例代码如下:

> get k "v" > multi OK > set k v2 QUEUED > expire k 10s QUEUED > exec 1) OK 2) (error) ERR value is not an integer or out of range > get k "v2"

执行命令解释如下图所示:

image.png


从以上结果可以看出,即使事务队列中某个命令在执行期间发生了错误,事务也会继续执行,直到事务队列中所有命令执行完成。

2)入列错误导致事务结束

示例代码如下:

> get k "v" > multi OK > set k v2 QUEUED > multi (error) ERR MULTI calls can not be nested > exec 1) OK > get k "v2"

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzyfg.html