事务是一组具备原子性操作的命令集合。在这一组命令中,要么全部执行成功,要么全部执行失败。
有关事务的四大特性的具体讲解可以参考该文章 http://mindoc.qqdeveloper.com/docs/mysql/mysql-1cj2eksj770bg
Redis在事务中的命令是添加到一个命令队列里面,等待事务提交之后,则一一执行命令队列里面的命令。
客户端一:负责开启事务并写入缓存数据。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set user:id:1 1
QUEUED
127.0.0.1:6379> exec
1) OK
事务执行exec命令返回的是,事务中执行的命令数量以及对应的结果。
客户端二:负责读取缓存中的数据。
# 客户端一执行set之后,执行exec之前。
127.0.0.1:6379> get user:id:1
(nil)
# 客户端执行exec之后。
127.0.0.1:6379> get user:id:1
"1"
客户端一:负责开启事务,并使用watch监听key。
# 监听key之前查看值
127.0.0.1:6379> get age
"1"
# 开启监听
127.0.0.1:6379> watch age
OK
# 开启事务
127.0.0.1:6379> multi
OK
# 修改被监听的key值
127.0.0.1:6379> set age 2
QUEUED
# 提交事务(发现返回的是nil,表示未执行成功。)
127.0.0.1:6379> exec
(nil)
# 重新获取监听的key值
127.0.0.1:6379> get age
"3"
客户端二:负责修改客户端一中监听的key。
# 在客户端一执行watch命令,开启事务之后,提交事务之前执行。
127.0.0.1:6379> set age 3
OK
# 在客户端一执行exec命令之后执行。
127.0.0.1:6379> get age
"3"
通过2中的演示,你会发现在事务开启之前对key做了监听。事务正常提交之后,被监听的key在事务中执行的命令是不会被执行的。unwatch对监听的key,取消监听事件。此时的取消监听不能放在事务中,只能在事务开启之前对key的监听事件做取消。事务命令异常处理
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set user:name zhangsan
QUEUED
127.0.0.1:6379> set user:age 1
QUEUED
127.0.0.1:6379> set user:sex max
QUEUED
# 执行一条命令错误的操作
127.0.0.1:6379> set a
(error) ERR wrong number of arguments for 'set' command
# 提交事务
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys *
1) "user:id:1"
2) "name"
3) "age"
通过上面的演示,在事务中执行一条错误的语法命令,整个事务都将不会被执行。
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set mu:id 1
QUEUED
# 执行一个语法不当的操作
127.0.0.1:6379> incr name
QUEUED
127.0.0.1:6379> set mu:age 2
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
通过上面的演示,在事务中执行了一条语法不当的的操作,最终提交事务后。事务中的正确命令依旧不被执行了。这不符合事务原子性的特点。