Redis事务是一个单独的隔离操作:事务中的所有命令都会被序列化、按顺序的执行,事务在执行的过程中,不会被其他客户端发来的命令请求所打断。
Redis事务的主要作用是串联多个命令防止别的命令插队。
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
- 开始事务。
- 命令入队。
- 执行事务。
Multi、Exec、discard
从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exce后,Redis会将之前的命令队列中的命令依次执行。
discard:中断组队过程
以上为成功的情况,下面列举事务错误处理:
1.在组队时有命令错误,最终该事务中的所有命令均不执行
2.若组队阶段没有发生错误,在执行阶段发生错误,失败的命令无法执行,其他的命令可以成功执行
事务冲突
例:
当前有10000元,一个请求消费8000,一个请求消费5000,一个请求消费1000
导致结果为-4000.
对于以上事务冲突问题,我们通过加锁的方式解决
悲观锁
即很悲观,每次去拿数据时都认为别人会修改,所以在每次获取数据时都上锁,使别人无法获取数据直至你使用完写回为止。
传统的关系型数据库里面用到了很多这种锁机制,比如行锁、表锁、读锁、写锁,都是在进行操作之前先上锁
缺点:效率较低,只能一个人一个人的使用
乐观锁
即比较乐观,每次拿数据时都认为别人不会修改,所以不进行上锁,但是在更新时会判断一下在此期间有没有人去更新这个数据(采用版本号机制)。
乐观锁适用于读操作较多的应用类型,提高吞吐量。例如:抢票
利用check-and-set机制实现事务
WATCH key[key...](乐观锁的使用)
在执行multi之前,先执行watch key1 [key2]来监视一个或多个key,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
例:在第一个窗口中对balance进行修改自动打断第二个窗口中的事务
unwatch:取消对所有key监控
Redis事务的三特性
单独的隔离操作
事务中的所有命令都会被序列化、按顺序的执行,事务在执行的过程中,不会被其他客户端发来的命令请求所打断。
没有隔离级别的概念
队列中的命令在没有提交前不会实际执行
不保证原子性
食物中如果有一条命令执行失败,其后的命令依然被执行,没有回滚