十二、Redis进阶-事务参考记录
事务介绍
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没有被事务中的命令修改。