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是可以支持乐观锁的