redis事务和乐观锁

事务
redis事务的本质是一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行的过程中,会按照顺序执行。具有一次性,顺序性,排他性。
redis事务有没有隔离级别的概念,所有的命令在事务中,并没有直接被执行,只有发起执行命令的时候才会执行。
redis的单条命令是保持原子性的,但是事务不保证原子性
redis事务流程
开启事务(multi)
命令入队(……)
执行事务(exec)
正常执行事务

#开启事务
127.0.0.1:6379[2]> multi 
OK
#命令入队
127.0.0.1:6379[2]> set myset hello
QUEUED
127.0.0.1:6379[2]> set myset2 world
QUEUED
127.0.0.1:6379[2]> get myset
QUEUED
#命令执行
127.0.0.1:6379[2]> exec 
1) OK
2) OK
3) "hello"

放弃事务

#开启事务
127.0.0.1:6379[2]> multi 
OK
127.0.0.1:6379[2]> set k1 v1
QUEUED
127.0.0.1:6379[2]> set k2 v2
QUEUED
#取消事务
127.0.0.1:6379[2]> discard 
OK
#事务队列中的命令都会被放弃
127.0.0.1:6379[2]> get k2 
(nil)

事务中的异常
编译型异常(代码有问题,命令有错)事务中所有的命令都不会被执行

127.0.0.1:6379[2]> multi
OK
127.0.0.1:6379[2]> set k1 v1
QUEUED
127.0.0.1:6379[2]> set k2 v2
QUEUED
127.0.0.1:6379[2]> set k3 v3
QUEUED
#错误的命令
127.0.0.1:6379[2]> getset k3 
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379[2]> set k4 v4
QUEUED
127.0.0.1:6379[2]> exec#执行事务报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379[2]> get k4#所有的命令都会被放弃
(nil)

运行时异常,如果事务队列中存在错误,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常。

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> multi
OK
#会执行失败
127.0.0.1:6379> incr k1 
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
#虽然第一条命令出错,但是后面的还是会执行
1) (error) ERR value is not an integer or out of range
2) OK
3) "v2"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379>

悲观锁乐观锁
悲观锁:很悲观, 认为什么时候都会出问题,无论做什么都会加锁 !
乐观锁:很乐观,认为很么时候都不会出问题,所以不会上锁 ! 在更新数据的时候去判断一下, 在此期间是否有人修改过这个数据。
一般规则是操作时获取version,更新的时候比较version。
说明:大多数是基于数据版本(version)的记录机制实现的,即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据表增加一个version字段来实现,在读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1 此时,将提交数据的版本号与数据表对应记录的当前版本号进行对比,如果提交的数据版本号大于数据库当前的版本号,则给与更新,否则认为是过期数据。
监视测试

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
#监视money对象
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

测试多线程修改值,使用watch 可以当做redis的乐观锁操作

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
#执行之前,开启另一个线程去修改money的值,这个时候就会导致事务执行失败。
127.0.0.1:6379> exec
(nil)

出现上面错误要解锁

#如果发现事务执行失败就先解锁
127.0.0.1:6379> unwatch 
OK
#获取最新的值再次监控,类似select version
127.0.0.1:6379> watch money 
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 1000
QUEUED
#执行之前会先比较version ,一样就会执行成功,反正失败
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 1000
127.0.0.1:6379>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值