Redis 可以通过 MULTI,EXEC,DISCARD 和 WATCH 等命令来实现事务(transaction)功能。

Redis 的单个命令都是原子性的,所以这里确保事务性的对象是命令集合。

Redis 将命令集合序列化并确保处于同一事务的命令集合连续且不被打断的执行

Redis不支持回滚操作

redis如何提交事务处理 redis事务_EXEC

 

在介绍 Redis 事务相关命令前,我们先上一张图,这张图很好的描述了 Redis 事务的执行过程,在图里体现了部分命令,WATCH 命令会在后面单独介绍,需要注意的一点是这张图里面的 queue 队列,理解它的作用,然后再结合相关命令的介绍,就能够很快搞明白 Redis 事务。

1)MULTI:用于标记事务块的开始。Redis 会将后续的命令逐个放入队列中,然后使用 EXEC 命令原子化地执行这个命令序列。

127.0.0.1:6379> multi # 开启事务

OK

127.0.0.1:6379> set k1 alan # 设置 k1

QUEUED # k1 加入队列

127.0.0.1:6379> set k2 tom # 设置 k2

QUEUED # k2 加入队列

2)EXEC:在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态。

127.0.0.1:6379> exec

1) OK

2) OK

使用 EXEC 命令原子化地执行这个命令序列,刚刚我们设置了 k1 和 k2 两条命令,执行EXEC 命令后,给我们反馈了两个 OK,说明上述两条命令全部执行成功。

3)DISCARD:清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。

127.0.0.1:6379> multi

OK

127.0.0.1:6379> set k3 lucy

QUEUED

127.0.0.1:6379> set k4 jack

QUEUED

127.0.0.1:6379> discard

OK

4)WATCH:当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的状态。注意:使用该命令可以实现 Redis 的乐观锁。

(1)对于 WATCH 命令的演示就稍微麻烦一些,这里我们在 Xshell 中开启两个 ssh 渠道,并且都连接到了单机的 Redis 服务(两个 ssh 渠道连接的是同一个 Redis 服务)

(2)在第一个窗口中使用 WATCH 命令,监控 data1,并开启事务,添加设置 data2 的命令到命令队列中

(3)然后在第二个窗口中,改变 data1 的值

(4)回到第一个窗口,执行 EXEC 命令,此时会发现返回了一个 nil,而且我们获取 data2 的值,返回的也是 nil,这就说明,当被监控的数据发生改变后,开启的事务执行是无法成功的,只有被监控的数据不发生变化,事务才能正常执行。

(5)UNWATCH:清除所有先前为一个事务监控的键。

但是,Redis 的事务和我们平时理解的关系型数据库的事务不同。我们知道事务具有四⼤特性:

1. 原⼦性,2. 隔离性,3. 持久性,4. ⼀致性。

1. 原⼦性(Atomicity): 事务是最⼩的执⾏单位,不允许分割。事务的原⼦性确保动作要么全部完成,要么完全不起作⽤;

2. 隔离性(Isolation): 并发访问数据库时,⼀个⽤户的事务不被其他事务所⼲扰,各并发事务之间数据库是独⽴的;

3. 持久性(Durability): ⼀个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发⽣故障也不应该对其有任何影响。

4. ⼀致性(Consistency): 执⾏事务前后,数据保持⼀致,多个事务对同⼀个数据读取的结果是相同的;

Redis 是不⽀持 roll back 的,因⽽不满⾜原⼦性的(⽽且不满⾜持久性)。

Redis官⽹也解释了⾃⼰为啥不⽀持回滚。简单来说就是Redis开发者们觉得没必要⽀持回滚,这样更简单便捷并且性能更好。Redis开发者觉得即使命令执⾏错误也应该在开发过程中就被发现⽽不是⽣产过程中。

你可以将Redis中的事务就理解为 :Redis事务提供了⼀种将多个命令请求打包的功能。然后,再按顺序执⾏打包的所有命令,并且不会被中途打断。