Redis中的事务和乐观锁实现

redis事务相关命令:

开启事务:multi

关闭事务:discard

提交事务:exec

 正常执行事务情况:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name zhangsan
QUEUED
127.0.0.1:6379> set age 20
QUEUED
127.0.0.1:6379> set high 172
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) OK
127.0.0.1:6379>

 放弃事务的情况

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name zhangsan
QUEUED
127.0.0.1:6379> set age 23
QUEUED
127.0.0.1:6379> set high 172
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379>

编译异常,代码错误,命令错误情况

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name zhangsan
QUEUED
127.0.0.1:6379> set age 26
QUEUED
127.0.0.1:6379> set high 172
QUEUED
127.0.0.1:6379> getset name    ###错误命令
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set wight 45
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>
 

 运行时异常,除了语法错误不会被执行且抛出异常后,其他的正确命令可以正常执行

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name zhangsan
QUEUED
127.0.0.1:6379> set age 23
QUEUED
127.0.0.1:6379> get age
QUEUED
127.0.0.1:6379> incr name
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) "23"
4) (error) ERR value is not an integer or out of range
127.0.0.1:6379> get age
"23"
127.0.0.1:6379>
 

 总结:

由以上可以得出结论,Redis是支持单条命令事务的,但是事务并不能保证原子性(开启事务后执行多条命令)!

Redis乐观锁的实现

多线程测试watch

线程一(打开一个命令行窗口):

127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set cost 0
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby money 20
QUEUED
127.0.0.1:6379> decrby cost 10
QUEUED
127.0.0.1:6379> exec    ###当线程二执行后在执行exec命令
(nil)
127.0.0.1:6379>

线程2(再打开一个命令行窗口) 该事务在线程一事务提交前先执行 

 发现当线程二中修改了key为money的值后,然后线程一执行exec命令后监视器发现money的值发生了变化,因此事务执行失败

乐观锁与悲观锁

悲观锁:什么时候都会出问题,所以一直监视着,没有执行当前步骤完成前,不让任何线程执行,十分浪费性能!一般不使用

乐观锁:在更新数据的时候判断一下,在此期间判断监视的这个数据是否发生变动,没有变动则正常执行,否则执行错误。

总结:

在redis中单条命令是原子性的,但是 事务不保持原子性。

redis是可以支持乐观锁的

猜你喜欢

转载自blog.csdn.net/qq_38423256/article/details/128694119