本质
一组命令的集合,一次性执行,按顺序执行,排他性(不允许被其他人干扰)。
有原子性?
Redis单条命令有原子性,但是事务不保证原子性!!!和Mysql是不同的!!!
有隔离级别?
没有。
所有命令在事务中,并没有被直接执行,而是在发起执行命令的时候才执行。
----队列
set
set
set
...
---执行
正常执行事务
- 开启事务(multi)
- 命令入队: 正常写命令即可
- 执行事务 (exec)
放弃事务
- 开启事务(multi);
- 命令入队:正常写命令即可
- 放弃事务(Discard)
编译型异常
当代码有问题,命令有错的时候,事务中的所有命令都不会被执行,因为编译都没通过。
如下,有一行命令没有通过编译,当执行exec时,所有的命令都不会被执行。
运行时异常
例如 1 / 0, 该错误在编译时无法检查出来,只有在运行时才会被发现。此时其他命令可以正常执行,错误命令抛出异常。因此事务没有原子性。如下,可以看到第一条命令报错了,但是后面的命令都正常执行了。
监控(watch)
悲观锁
很悲观,认为什么时候都会出问题,无论做什么都会加锁。例如你上厕所的时候,一定锁门,因为你总认为外边有人要冲进来,不锁门不行的。
悲观锁最大的问题是效率低下。
乐观锁
很乐观,认为什么时候都不会出现问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据。
Mysql中用Version来实现乐观锁。
- 获取version
- 更新的时候比较version
Redis监控测试
正常执行成功
在watch的过程中,money的数据没有发生变动,可以正常执行成功。
多线程修改值后,修改失败(当乐观锁来操作)
线程1:
此时线程1并未执行事务,线程2插入进来,修改了money值。
线程1执行exec来执行事务,因为加了watch,redis知道值被修改了,于是本次事务执行失败、
解决办法
- 先unwatch来解锁
- 重新watch money
- 开启事务,重新入队,执行。