Redis中事务Multi命令及监控键值Watch命令
知识回顾:
通过对Redis中的String的命令做了充分的讲解以及实践学习
通过对Redis中String类型之Bit命令的详解以及Bit命令的实践进行了学习
通过对Redis中的Hash类型以及Hash中常用命令的实践学习
通过对Redis之List类型的详解&List类型中常用命令的实践的学习
通过对Redis之Set类型的详解&Set类型中常用命令的实践的学习
通过对Redis之ZSet类型的详解&ZSet类型中常用命令的实践的学习
通过对Redis中消息的发布和订阅以及命令的实践学习
Redis中的事务概念
Redis是NOSQL数据库,所以也存在事务,但是Redis的事务和关系型数据库的事务是有区别的。
Redis事务命令Multi
Redis中开启事务的命令很简单,通过multi命令直接开启即可。
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)>
在MULTI命令执行之后,我们可以继续发送命令执行,但此时命令不会立即执行,而是保持到一个队列中,Redis会返回给我们一个QUEUED阻塞的状态,等待最后EXEC命令的执行。
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set username liu
QUEUED
127.0.0.1:6379(TX)> set password 123
QUEUED
127.0.0.1:6379(TX)> set age male
QUEUED
127.0.0.1:6379(TX)> set age 18
QUEUED
127.0.0.1:6379(TX)> set sex male
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) OK
4) OK
5) OK
127.0.0.1:6379>
事务异常
事务中的异常有两种情况:
进入队列之前发生错误
比较常见的命令错误,此类异常redis的处理方式是,服务器会对进入队列失败的情况进行记录,在执行exec命令提交的时候,对于该命令不会执行并放弃这个事务。
注意事项:redis事务中有一个异常并不会造成其他命令的回滚,其它事务正常执行,错误的异常最后返回错误信息!
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set username pan
QUEUED
127.0.0.1:6379(TX)> set password 111
QUEUED
127.0.0.1:6379(TX)> set age male female
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) (error) ERR syntax error
127.0.0.1:6379>
执行exec命令后发生的异常
对于这种情况,redis中也不会做特别的处理。事务中的命令继续执行。
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set username zuo
QUEUED
127.0.0.1:6379(TX)> incr username
QUEUED
127.0.0.1:6379(TX)> incrby username 7
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) (error) ERR value is not an integer or out of range
127.0.0.1:6379>
为什么Redis没有事务回滚的操作呢?看看官网怎么说?
Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
Redis中监控键值对的Watch命令
Watch命令可以监控一个或多个键,一旦其中有一个键被修改或者删除的时候,之后的事务就不会执行。
监控一直持续到exec命令。
事务中的命令是在exec之后才执行的,所以在Multi命令后可以修改Watch监控的键值。
假设我们通过watch命令在事务执行之前监控了多个Keys,倘若在Watch之后有任何Key的值发生了变化,exec命令执行的事务都将被放弃,Redis给我们返回(nil),同时返回Null multi-bulk应答以通知调用者事务执行失败。
exec后会自动执行unwatch命令,撤销监控。
watch的命令是必须在multi的前面的,如果在multi开启事务之后是错误的,会报出异常
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set username huang
QUEUED
127.0.0.1:6379(TX)> set age 13
QUEUED
127.0.0.1:6379(TX)> set sex male
QUEUED
127.0.0.1:6379(TX)> set password root
QUEUED
127.0.0.1:6379(TX)> watch age sex password username
(error) ERR WATCH inside MULTI is not allowed
127.0.0.1:6379(TX)> watch age
(error) ERR WATCH inside MULTI is not allowed
127.0.0.1:6379(TX)>
watch的命令是在multi的前面,然后执行正常的操作后exec
127.0.0.1:6379> set username xue
OK
127.0.0.1:6379> set password root
OK
127.0.0.1:6379> set age 12
OK
127.0.0.1:6379> set sex female
OK
127.0.0.1:6379> watch username password age sex
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set username liu
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
127.0.0.1:6379>
watch的命令是在multi的前面,如果在watch命令之后,multi命令之前修改我们之前通过watch监听的key值,然后执行操作exec,会出现错误。
127.0.0.1:6379> set username yan
OK
127.0.0.1:6379> watch username
OK
127.0.0.1:6379> set username zuo
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379>
Redis之UnWatch命令
撤销对一个key的监控。
127.0.0.1:6379> set username psx
OK
127.0.0.1:6379> watch username
OK
127.0.0.1:6379> set username zs
OK
127.0.0.1:6379> unwatch
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> exec
(empty array)
127.0.0.1:6379> get username
"zs"
127.0.0.1:6379>