「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」
事务
要么同时成功,要么同时失败,原子性!
redis单条命令是保证原子性,但是事物是不保证原子性的!
有发起执行命令的时候才会执行
一次性、顺序性、排他性
Redis事物本质:一组命令的集合!,一个事物中的所有命令都被序列化,在事务执行过程中会按照顺序执行
redis事务没有隔离级别的概念
所有的命令在事务中并没有直接被执行,只
redis事务
开启事务 # multi
命令入队 #set key1 v1
执行事务 #exec
正常执行事务
放弃事务 #discard
例子
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> get k1
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) "v1"
127.0.0.1:6379>
异常
编译型异常(代码有问题!命令有错!)事务中所有命令都不会被执行!
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> setget k2
(error) ERR unknown command `setget`, with args beginning with: `k2`,
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 k3
(nil)
运行时异常如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常
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> incr k2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (error) ERR value is not an integer or out of range
4) OK
127.0.0.1:6379> get k3
"v3"
127.0.0.1:6379>
redis实现乐观锁(面试常问)
redis实现乐观锁(面试常问)
悲观锁:
无论做什么都加锁
乐观锁:
获取version
很乐观,认为什么时候都不会出现问题,所以不会上锁。更新数据的时候去判断一下,在此期间是否修改过这个数据,watch
Redis监视测试
unwatch 放弃监视 解锁
watch money重新监视
如果发现事务执行失败就先解锁,获取最新的值再次监视执行事务,exec比对监视的值是否发生变换如果没有变换执行成功,如果变换了执行失败
事务执行成功
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20
127.0.0.1:6379>
模拟两个线程,一个线程修改了事务中的数据,事务执行失败
线程一
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money #监视数据上锁
OK
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec #执行事务的时候 判断money值发现改变(被线程2修改为1000)事务执行失败
(nil)
127.0.0.1:6379> unwatch #先解锁
OK
127.0.0.1:6379> watch money #在上锁重新执行事务
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 980
2) (integer) 20
127.0.0.1:6379>
线程二
127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379>