redis的事务
- redis没有隔离级别的概念
- redis的单条指令是原子性的,但是事务不保证原子性
redis的事务:
1、开启事务multi
2、命令入队(编写一些命令)
3、执行事务exec
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379(TX)> set key1 v1
QUEUED
127.0.0.1:6379(TX)> set key2 v2
QUEUED
127.0.0.1:6379(TX)> exec #执行事务
1) OK
2) OK
放弃事务DISCARD
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379(TX)> set key3 v3
QUEUED
127.0.0.1:6379(TX)> DISCARD #放弃事务
OK
事务执行出现异常
- 编译时异常(如果事务队列中一个命令编译错误,就都不执行)
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379(TX)> set key1 v1
QUEUED
127.0.0.1:6379(TX)> setsjcs #错误的命令
(error) ERR unknown command 'setsjcs', with args beginning with:
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get key1
(nil) #所有的命令都不执行,之前的key1也没有设置进去
- 运行时异常,如果事务队列中某条命令运行时异常,其他的命令是可以正常执行的
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379(TX)> set key1 "v1"
QUEUED
127.0.0.1:6379(TX)> INCR key1 #对字符串进行加一操作
QUEUED
127.0.0.1:6379(TX)> set key2 v2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range #运行时的异常
3) OK
127.0.0.1:6379> get key1
"v1"
127.0.0.1:6379> get key2
"v2"
redis的监视(watch)
-
悲观锁:
很悲观,认为什么时候都会出现问题,无论干什么都要加锁。 -
乐观锁:
很乐观,认为什么时候都不会出问题,只有更新的时候会去判断一下此期间是否有人更改过数据 -
先查找数据库的version字段
-
更新时判断version是否和之前查的一致,一致就更新,不一致就不更新
监视
正常执行
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(TX)> DECRBY money 20 #总钱数减少20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20 #拿出的钱数增加20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20
当事务执行的过程中有其他的线程来修改了数据,那么就会撤销此次事务操作
127.0.0.1:6379> watch money #监视总钱数
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 20 #总钱数减20
QUEUED
127.0.0.1:6379(TX)> incrby out 20 #拿出的钱加20
QUEUED
127.0.0.1:6379(TX)> exec #事务执行之前有人对数据进行了修改,因此事务执行失败
(nil)
watch加锁,unwatch解锁,如果事务执行失败,就先解锁再加锁