Redis事务管理
用过其他关系型数据库(比如msql)的肯定都指定,在关系型数据库里面的事务可以保证多个命令操作要么同时成功,要么同时失败。并且在执行事务的时候,可以有隔离级别。
但是在Redis中的事务,只是保证事务同时执行多个命令,并且不会被其他客户端的命令所打断,但是,如果在执行的时候发现中断,错误之类的,Redis中的事务是没有回滚的功能。
在Redis中提供了DISCART、EXEC、MULTI、UNWATCH、WATCH这个几个命令来操作事务。
事务的用法
①通过MULTI命令,开启一个事务,这时候,客户端可以发送任意多条命令,这些命令不会立即执行,而是放到一个队列中。
②通过EXEC命令,可以一次性执行队列中的命令。
③如果命令加入队列中之后,我们不想执行这个事务了,还可以通过DISCARD来放弃事务,这时候队列会被清空。
实例:
127.0.0.1:6379> multi OK 127.0.0.1:6379> get name QUEUED 127.0.0.1:6379> set name zhangsan QUEUED 127.0.0.1:6379> pop age (error) ERR unknown command 'pop' 127.0.0.1:6379> set age 20 QUEUED 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get name (nil) 127.0.0.1:6379> multi OK 127.0.0.1:6379> get name QUEUED 127.0.0.1:6379> set name zhangsan QUEUED 127.0.0.1:6379> exec 1) (nil) 2) OK 127.0.0.1:6379> exec (error) ERR EXEC without MULTI 127.0.0.1:6379>
可以看到,在pop age这个命令入队的时候i,发生了错误,然后在exec的时候,发现这个事务已经被取消了。
而在后面,get name返回的是nil,但是事务还是被执行了。
需要注意的是,在执行的时候即使在其中某个命令出现错误了,redis还是会继续执行事务里的其他命令,而不会中止执行操作。
使用CHECK-AND-SET实现乐观锁
乐观锁的意思就是锁定某个资源,但是如果其他客户端也需要访问这个资源的时候,则释放资源给其他客户端访问。
WATCH命令可以用来监视某个键,并且可以发觉这些键是否被改动了。如果至少有一个被监视的键在EXEC执行之前被修改了,那么整个事务都被被取消,EXEC会返回nil-reply来表示事务已经失败。
127.0.0.1:6379> get name "zhangsan" 127.0.0.1:6379> watch name OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> set age 20 QUEUED 127.0.0.1:6379> set address shanghai QUEUED ##################### #这时候,在启动一个客户端,修改name的值 ##################### 127.0.0.1:6379> exec (nil) 127.0.0.1:6379>
[root@localhost 08:36 ~]# redis-cli 127.0.0.1:6379> set name lisi OK 127.0.0.1:6379>
Redis脚本
Redis脚本,本身也是一种事务,所以在事务中可以完成的事情都可以通过脚本来完成。并且脚本更加简单,更加快速。
但是由于脚本是在Redis2.6版本中才引入的,而事务很早就已经存在了,所以现在的版本中两种都存在,
但是不排除以后的版本会删掉事务的功能。