redis-transaction
注意
-
不支持回滚操作
是因为redis是先执行指令然后做日志,所以即使发生异常,没有可以用来执行回滚操作的日志。 - 只保证事物的
隔离性
, 不保证原子性
. -
redis
禁止在multi
和exec
之间执行watch
指令,而必须在multi
之前做好盯住关键变量,否则会出错。
事物的过程
multi:
事物的开始(创建一个事物);
exec:
事物的执行;
discard:
丢弃这个事物;
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr books
QUEUED
127.0.0.1:6379> incr books
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 2
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr books
QUEUED
127.0.0.1:6379> incr books
QUEUED
127.0.0.1:6379> incr books
QUEUED
127.0.0.1:6379> exec
1) (integer) 3
2) (integer) 4
3) (integer) 5
原理
redis 单线程且本身保证有序,且能保证不被其他指令打扰.--仅仅是保证了隔离性
redis multi和exec命令不能保证原子性,中间执行的多个命令有一个失败了,不会影响其他命令的执行.
redis multi和exec仅仅保证一堆命令不被插队,顺序执行.原理是在server端开启了一个事物队列.
优化
建议使用pipeline 提升性能.
pipe = redis.pipeline(transaction=true)
pipe.multi()
pipe.incr("books")
pipe.incr("books")
values = pipe.execute()
避免并发问题
悲观锁: 分布式锁
乐观锁: watch机制
watch机制
> watch books
OK
> incr books # 被修改了
(integer) 1
> multi
OK
> incr books
QUEUED
> exec # 事务执行失败
(nil)
watch
会实时检查观察的key
是否被改变,如果改变了exec
提交会执行失败,返回null
.