redis学习笔记5(redis事务)

时间:2022-05-06 06:00:16

redis事务是可以一次执行多个命令,本质上是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不允许加塞。

redis只能保证一个client发起的事务中的命令可以连续的执行,中间不会插入其他client的命令。由于redis是由单线程来处理所有client的请求,所有可以很容易做到这点。一般情况下redis接收一个client发来的命令后会立即处理并返回结果。如下所示:

127.0.0.1:6379> clear
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"

redis事务是通过执行multi命令开始,该连接后续的命令并不是立即执行,而是先放到一个队列中,当次连接收到exec命令后,redis会顺序的执行队列中的所有命令。并将所有命令的运行结果打包到一起返回给client,然后此链接就结束事务。

事务通常会使用MULTI,EXEC,WATCH等命令来完成,redis实现事务实现的机制与常见的关系型数据库有很大的却别,比如redis的事务不支持回滚,事务执行时会阻塞其它客户端的请求执行。

#redis事务开始与multi
127.0.0.1:6379> MULTI
OK
//后续的命令不立即执行,而是先放到queued中,不管做什么操作都会放到队列中

127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> LPUSH list1 a b c d e
QUEUED
127.0.0.1:6379> LLEN list1
QUEUED
127.0.0.1:6379> LRANGE list1 0 -1
QUEUED
#最后当执行exec时,redis有序执行完所有命令,并把返回打包一起到client
127.0.0.1:6379> EXEC
1) OK
2) OK
3) (integer) 5
4) (integer) 5
5) 1) "e"
2) "d"
3) "c"
4) "b"
5) "a"
127.0.0.1:6379>

放弃事务。

//上一段代码片中,
127.0.0.1:6379> KEYS *
1) "list1"
2) "k2"
3) "k1"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v100
QUEUED
127.0.0.1:6379> DISCARD
OK
// 执行discard命令后,发现k1还是之前的值,说明discard命令其实就是清空事务的命令
// 队列并退出事务上下文。
127.0.0.1:6379> get k1
"v1"

redis事务,数据一致性

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
// 执行一个错误的命令

127.0.0.1:6379> LRANGE k2
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> set k3 v3
QUEUED
// 结束事务时,报错。

127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
// 在一个事务中,原子一致。

127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> get k2
(nil)
127.0.0.1:6379> get k3
(nil)
127.0.0.1:6379>

redis部分支持事务例子。

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
#k1值不能够进行算数计算,redis没有回滚。
127.0.0.1:6379> INCR k1
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
#结束之后正常的命令显示出结果,错误的命令返回错误信息。
127.0.0.1:6379> EXEC
1) OK
2) (error) ERR value is not an integer or out of range
3) "v1"
4) OK

在Redis的事务中,WATCH命令可用于提供CAS(check-and-set)功能。WATCH是一个乐观锁,它可以在EXEC命令执行之前,监视任意数量的数据库键,并在执行EXEC命令时判断是否至少有一个被watch的键值已经被修改过。如果被修改就放弃事务的执行,如果没有被修改就清空watch的信息,执行事务列表里的命令。

unwatch:
顾名思义可以看出它的功能是与watch相反的,是取消对一个键值的“监听”的功能能 。

// watch 监视key-balance
127.0.0.1:6379> WATCH balance
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set balance 1000
QUEUED
127.0.0.1:6379> EXEC
1) OK
// 在执行exec之前,没有对key:balance修改,事务正常执行.清空watch信息,执行了事务列表中的命令
127.0.0.1:6379> get balance
"1000"

127.0.0.1:6379> WATCH balance
OK
// 监视balance且在事务执行之前,修改了balance的值。
127.0.0.1:6379> set balance 20
OK
127.0.0.1:6379> WATCH balance
OK
127.0.0.1:6379> set balance 500
OK
// 可以看到执行exec,结果为nil。放弃事务执行。
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get balance
"20"