Redis学习笔记(5)-redis事务原理及其应用

Redis中的事务是一组redis命令的集合。这一组redis命令和一个普通的redis命令一样,都是redis执行的最小单位。这一组redis命令要么不执行,要么全部执行。事务中的所有redis命令都是按顺序执行,中间不会被插入其他不相关的命令。

redis事务的开启,执行和关闭

要打开事务,可以使用multi命令,之后键入的redis命令,都会被缓存到队列里面来,这一点从返回值queued就可以看出来。想要执行事务,可以使用exec命令,其会返回所有事务中命令的返回值。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name cy
QUEUED
127.0.0.1:6379> set age 21
QUEUED
127.0.0.1:6379> incr age
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (integer) 22

当事务执行完毕后,我们再去查询name和age的值,可以看出已经生效:

127.0.0.1:6379> get name
"cy"
127.0.0.1:6379> get age
"22"

我们可以在执行exec提交事务之前使用discard命令取消事务:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr age
QUEUED
127.0.0.1:6379> incr age
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> get age
"22"

可以看出,我们在一个开启的事务中,使用incr增加age的值,但是由于最后使用discard命令取消了事务,导致我们再次查询age值的时候发现其值未曾发生变化。这说明事务被成功取消了,里面的命令并未得到执行。

watch命令的介绍

有时候我们有一种使用场景,要监控A变量来对B变量进行赋值,但是如果得到A的值后到计算出B的值这段时间内,如果A的值发生变化,这时候再进行B的赋值,就会形成误操作。所以需要一种机制确保在拿到A的值到最后对B赋值成功,这期间A的值不能发生变化。watch可以解决这个问题。这种机制有点类似于数据库解决并发问题的乐观锁。

127.0.0.1:6379> set A 22
OK
127.0.0.1:6379> get A
"22"
127.0.0.1:6379> watch A
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set B 22
QUEUED
127.0.0.1:6379> exec
1) OK
127.0.0.1:6379> get B
"22"

如果在提交exec的时候,发现A的值已经发生变化了,此时事务不会不执行:

127.0.0.1:6379> watch A
OK
127.0.0.1:6379> set A 23
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set B 23
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get B
"22"

redis事务的两点特性

1)如果事务队列里面的内容语法上有错误,则exec提交执行,直接报错返回,并清空队列,所有redis都不可以执行:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set color green
QUEUED
127.0.0.1:6379> ssset color green
(error) ERR unknown command `ssset`, with args beginning with: `color`, `green`,
127.0.0.1:6379> set size 24
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get color
(nil)
127.0.0.1:6379> get size
(nil)

2)如果命令的语法上没有错误,只是命令执行本身出错,则事务可以顺利推进:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set color red
QUEUED
127.0.0.1:6379> sadd color green
QUEUED
127.0.0.1:6379> set size 996
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 color
"red"
127.0.0.1:6379> get size
"996"

注意:第二种情况,虽然事务能顺利推进,但是出错后,并不提供回退的功能。这时候自己弄出的烂摊子,就靠自己处理了

redis事务的ACID

一句话总结,redis并不能保证事务的原子性,也不能保证事务的持久性,可以保证事务的一致性和隔离性。持久性比较特殊,也可以通过RDB或者AOF来支持。

redis事务的应用

分布式锁算是一个典型的应用场景,看过一个博主的帖子,用redis的事务来实现秒杀场景,有需要可以前去围观,写的真心不错。

https://blog.csdn.net/Evankaka/article/details/70570200

你可能感兴趣的:(redis)