十二、Redis进阶-事务参考记录

作者: 温新

分类: 【Redis】

阅读: 2180

时间: 2020-09-02 13:11:58

事务介绍

Redis中的事务(transaction)是一组命令的集合。事物与命令一样都是Redis的最小 执行单位,一个事务中的命令要么全部执行,要么全部不执行。

举个栗了,银行转账,A给B汇款,首先,系统从A的账号中将钱划走,然后向B的账户增加相应的金额。这个过程必须是同一个事务,要么全部执行,要么全部不执行。

事务执行流程

Redis事务可以一次执行多个命令,且有如下保证:

1)批量操作在发送exec命令前被放入队列缓存

2)收到exec命令后进入事务执行,事务中任意命令执行失败,其余命令依旧被执行

3)事务执行过程中,其他客户端提交的命令请求不会插入到事务执行命令序列中

一个事务从开始到执行经历三个阶段

1)开始事务 2)命令入列 3)执行事务

事务命令

multi开启一个事务

exec执行一个事务

watch监听一个或多个key

unwatch取消wacth命令对所有key的监听

discard取消事务

Redis事务实际案例

# 1)开启事务
127.0.0.1:6379>  multi
OK

# 2)执行命令
127.0.0.1:6379> sadd user:1:following 2
QUEUED
127.0.0.1:6379> sadd user:2:following 1
QUEUED

# 3)exec执行事务
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1

解释

1)multi命令告诉Redis开启事务,下面的命令都是同一个事务,你先不要执行,把它们存起来。

Redis回答“OK”。

2)接下来是我们要操作的命令了,执行两个sadd命令,Redis果然遵守的承诺,回答QUEUED,表示命令已经进入等待执行的事务队列中。

3)命令完毕后,使用EXEC命令告诉Redis我的命令完毕了,开始执行事务。Redis收到执行事务的命令之后,按照Redis命令发送的顺序依次执行。

Redis保证一个事务中的命令要么全部执行,要么全部不执行。如果在exec前客户端断线了,Redis则清空事务队列,事务中所有命令都不执行。

事务错误处理

语法错误,指命令不存在或着命令参数的个数不对,如下案例

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name ziruchu
QUEUED
127.0.0.1:6379> set name
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.

执行3个命令,一个正确,加入队列,其余存在语法错误。只要一个有语法错误,执行exec将直接返回错误

运行错误指命令执行时出现错误。

如用哈希类型操作集合类型的键,这种错误在被实际执行前,Redis无法发现,因此,事务中这样的命令会被Redis接受并执行。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name ziruchu
QUEUED
127.0.0.1:6379> sadd name php
QUEUED
127.0.0.1:6379> set name mysql
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK

127.0.0.1:6379> get name
"mysql"

实际操作可见,sadd name php出错,但set name mysql依旧被执行,Redis事务没有回滚功能,因此一定要小心。

watch监听一个或多个key

watch命令可以监听一个或多个键,一旦其中有一个键被修改或删除,之后的事务将不执行。监听一直持续到exec命令。

127.0.0.1:6379> set name php
OK
127.0.0.1:6379> watch name
OK
127.0.0.1:6379> set name ziruchu
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name mysql
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get name
"ziruchu"

上述案例中,首先设置一个name,其次监听name,其三再监听这个name,其四开启事务,其五设置name,其六执行事务。结果name没有被事务中的命令修改。

请登录后再评论