-
redis的单条命令是保证原子性的,但是事务不保证原子性!
-
redis的事务的本质是一组命令一起执行
- 一次性
- 顺序性
- 排他性
-
redis事务没有隔离级别的概念
-
redis事务的步骤
-
开启事务 (MULTI)
-
命令入队 (…)
-
执行事务 (exec)
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 k2 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> exec 1) OK 2) OK 3) "v2" 4) OK
-
-
放弃事务 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> DISCARD OK 127.0.0.1:6379> get k1 (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> stt k3 v3 #错误的命令 (error) ERR unknown command `stt`, with args beginning with: `k3`, `v3`, 127.0.0.1:6379> 127.0.0.1:6379> set k4 v4 QUEUED 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get k1 (nil)
-
运行时事务异常,跳过错误的命令继续执行后续命令
127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> INCR k1 #对字符串自增1 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> get k2 QUEUED 127.0.0.1:6379> exec #只跳过了错误的命令 其他命令正常执行 1) OK 2) (error) ERR value is not an integer or out of range 3) OK 4) "v2" 127.0.0.1:6379> get k3 "v3"
redis监控实现乐观锁
watch命令监控一个key
-
正常提交事务
#设置一个当前余额 100 127.0.0.1:6379> set money 100 OK #设置一个使用金额 0 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 #money减掉20 127.0.0.1:6379> DECRBY money 20 QUEUED #out增加20 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> get money "80" 127.0.0.1:6379> get out "20" #正常提交后,各数值是正确的
-
多线程操作情况下,事务执行失败
线程1:
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 #在这里时 线程2执行完成 此时再执行事务 会执行失败 #因为money已经在线程2中被改变 127.0.0.1:6379> EXEC (nil) 127.0.0.1:6379> get money "200" 127.0.0.1:6379> get out "0" 127.0.0.1:6379>
事务执行失败 UNWATCH 释放监视 再次重新监视
线程2:
127.0.0.1:6379> get money "100" 127.0.0.1:6379> get out "0" 127.0.0.1:6379> INCRBY money 100 (integer) 200 127.0.0.1:6379> get money "200" 127.0.0.1:6379> get out "0" 127.0.0.1:6379>
3. xxx