前言

Redis可以看成NoSQL类型的数据库系统, Redis也提供了事务, 但是和传统的关系型数据库的事务既有相似性, 也存在区别。Redis对事务的支持是部分支持

Redis事务简介

Redis的基本事务(basic transaction)需要用到MULTI命令和EXEC命令,Redis只能保证一个客户端发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个连接会进入一个事务的上下文,该连接后续的命令不会立即执行,而是先放在一个队列中,当执行exec命令时,redis会按照顺序的执行队列中的所有命令

Redis事务命令

java redis事务如何实现 redis事务的实现_Redis

事务的几种情况
1、正常执行

先看下面的例子:

java redis事务如何实现 redis事务的实现_java redis事务如何实现_02


通过上面的命令可以看到使用 multi 命令开启事务之后,执行的Redis命令返回结果 QUEUED(队列),表示命令并没有执行,而是暂时保存在Redis事务中,直到执行 exec 命令提交事务后才会执行上面的命令并且返回结果。只要是符合redis语法的命令都会入队成功,返回一个QUEUED。正常执行可以实现批处理的效果。

所以,事务正常执行的三个过程是:开启、入队、执行。

2、放弃事务

java redis事务如何实现 redis事务的实现_java redis事务如何实现_03


可以看到,当我们开启一个事务后,不想提交这个事务,我们可以使用discard命令来放弃这个事务。

3、事务对异常的处理机制

Redis执行命令的错误主要分为两种:

  • 1.命令错误:执行命令语法错误,比如说将 set 命令写成 sett
  • 2.运行时错误:命令语法正确,但是执行错误,比如说对非数字的值执行 incr命令

(1)、命令错误处理机制-----全体连坐

开启事务之后,往事务中添加的命令如果有命令错误(语法错误),那么整个事务中的命令都不会执行。

java redis事务如何实现 redis事务的实现_java redis事务如何实现_04


这个案例中,开启事务后其他命令添加返回QUEUED,第三条命令语法错误,导致整个事务中的命令都不会执行。

(2)、运行时错误处理机制-----冤头债主

如果语法没有错误,而执行过程中发生了运行时错误,Redis不仅不会回滚事务,还会跳过这个运行时错误,继续向下执行命令。

java redis事务如何实现 redis事务的实现_Redis_05


在这个案例中,可以看到最后事务的执行结果是第一条和第三条命令执行成功,第二条命令执行失败,所以第二条命令由于“jj”不是数字,在执行“incr"命令时运行错误导致执行失败,不仅没有回滚事务而且还不会影响后续第三条命令的执行。

5、watch监控

WATCH是一个乐观锁,它可以在exec命令执行之前,监视任意数量的数据库键,并在exec命令执行时,检查被监视的键是否至少有一个已经被修改过了,如果是服务器则拒绝执行事务,并向客户端返回代表事务执行失败的空回复.。

客户端一:

java redis事务如何实现 redis事务的实现_java redis事务如何实现_06


客户端二:

java redis事务如何实现 redis事务的实现_运行时错误_07


在上面这个例子中,我们监视了k1,k2,k3 三个键。当客户端一在执行事务过程中,客户端二已经对k3的值做了改动,这时候监视到键k3已经被修改过了,服务器则拒绝执行事务,并向客户端返回代表事务执行失败的空回复.。遇到这种情况,需要我们将最新的值摘出来,重新进行修改和提交。

需要注意两点:

1、使用UNWATCH可以取消对所以key的监视。
2、一旦执行了EXEC命令,之前加的监控锁都会被取消掉了。