Redis事务

核心知识点:

1.事务出错的类型有两种:

a.语法错误,事务不会被执行;

b.运行时报错,可能有部分事务会被执行成功。

2.watch可以监测在执行事务的过程中,如果目标被改变,将会导致事务无法执行。

熟悉关系型数据库的读者应该对事务比较了解,简单的说,事务表示一组动作,要么全部执行,要么全部不执行。

Redis提供了简单的事务功能,将一组需要执行的命令放到multi和exec两个命令之间。

multi命令代表事务开始,exec命令代表事务结束,它们之间的命令是原子顺序执行的。

例如,如果两个人需要成为好友,需要各自在自己的好友列表中加上对方的命令,如果只完成了一方,那么这组命令应该视作无效。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> sadd kebi:friend maoxian
QUEUED
127.0.0.1:6379> sadd maoxian:friend kebi
QUEUED

可以看到sadd命令此时的返回结果是QUEUED,代表命令并没有真正执行,而是暂时保存在Redis中。

在另外一个客户端查看刚才的添加操作,应该没有结果:

127.0.0.1:6379> sismember maoxian:friend kebi
(integer) 0

只有执行了exec之后,写入操作才算完成。

127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1

再次在另外一个客户端查询,有结果:

127.0.0.1:6379> sismember maoxian:friend kebi
(integer) 1

如果事务中命令出现错误,Redis的处理机制也不尽相同,一般主要有两种情况。

1.命令错误

如果事务的执行过程中,出现语法错误,会造成整个事务无法执行:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> sadd kebi:friend maoxian
QUEUED
127.0.0.1:6379> saddd maoxian:friend kebi
(error) ERR unknown command 'saddd'
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> sismember kebi:friend maoxian
(integer) 0   #并没有添加成功

2.运行时错误

也许语法不存在问题,但是执行过程中出现了错误,这种情况可能导致部分操作被执行成功。

(integer) 1
127.0.0.1:6379> multi
OK
127.0.0.1:6379> sadd kebi:friend xiaoniao
QUEUED
127.0.0.1:6379> zadd maoxian:friend 1 xiaoniao
QUEUED  #并没有语法错误,可maoxian:friend是集合,不是有序集合
127.0.0.1:6379> exec
1) (integer) 1
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> sismember kebi:friend xiaoniao
(integer) 1
127.0.0.1:6379> sismember maoxian:friend xiaoniao
(integer) 0

可以看到错误只是部分,但是并不是所有结果都没有执行,这就会导致问题。

Redis并不支持回滚功能,开发人员需要自己修复这类问题。

有些应用场景在事务之前,确保事务中的key没有被其他客户端修改过,才执行事务,否则不执行。Redis提供了watch命令来解决这类问题。

#客户端1
127.0.0.1:6379> set key java
OK
#客户端1
127.0.0.1:6379> watch key
OK
#客户端1
127.0.0.1:6379> multi
OK
#客户端2
127.0.0.1:6379> append key python
(integer) 10
#客户端1
127.0.0.1:6379> append key linux
QUEUED
#客户端1
127.0.0.1:6379> exec
(nil)
#客户端1
127.0.0.1:6379> get key
"javapython"

可以看到,如果在执行exec之前,所需的数据被修改了将会导致事务不能被执行。

Redis提供了简单的事务功能,之所说它简单,主要是因为它不支持事务中的回滚特性,

同时无法实现命令之间的逻辑关系计算,当然也体现了Redis的“keep it simple”的特性。

原文地址:https://www.cnblogs.com/yangmingxianshen/p/8098996.html