Redis事务是一个单独的隔离操作:事务中的所有命令都会被序列化、按顺序的执行,事务在执行的过程中,不会被其他客户端发来的命令请求所打断。

Redis事务的主要作用是串联多个命令防止别的命令插队。

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。

Multi、Exec、discard

从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exce后,Redis会将之前的命令队列中的命令依次执行。

discard:中断组队过程

redis的互斥锁和 redis命令解决并发冲突_redis

 

redis的互斥锁和 redis命令解决并发冲突_缓存_02

redis的互斥锁和 redis命令解决并发冲突_redis_03

以上为成功的情况,下面列举事务错误处理:

1.在组队时有命令错误,最终该事务中的所有命令均不执行

 

redis的互斥锁和 redis命令解决并发冲突_redis的互斥锁和_04

 2.若组队阶段没有发生错误,在执行阶段发生错误,失败的命令无法执行,其他的命令可以成功执行

redis的互斥锁和 redis命令解决并发冲突_Redis_05

 事务冲突

例:

当前有10000元,一个请求消费8000,一个请求消费5000,一个请求消费1000

redis的互斥锁和 redis命令解决并发冲突_redis_06

 导致结果为-4000.

对于以上事务冲突问题,我们通过加锁的方式解决

悲观锁

即很悲观,每次去拿数据时都认为别人会修改,所以在每次获取数据时都上锁,使别人无法获取数据直至你使用完写回为止。

传统的关系型数据库里面用到了很多这种锁机制,比如行锁、表锁、读锁、写锁,都是在进行操作之前先上锁

缺点:效率较低,只能一个人一个人的使用

redis的互斥锁和 redis命令解决并发冲突_缓存_07

 乐观锁

即比较乐观,每次拿数据时都认为别人不会修改,所以不进行上锁,但是在更新时会判断一下在此期间有没有人去更新这个数据(采用版本号机制)。

乐观锁适用于读操作较多的应用类型,提高吞吐量。例如:抢票

利用check-and-set机制实现事务

redis的互斥锁和 redis命令解决并发冲突_redis_08

WATCH key[key...](乐观锁的使用)

在执行multi之前,先执行watch key1 [key2]来监视一个或多个key,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

例:在第一个窗口中对balance进行修改自动打断第二个窗口中的事务

redis的互斥锁和 redis命令解决并发冲突_Redis_09

 

redis的互斥锁和 redis命令解决并发冲突_后端_10

 unwatch:取消对所有key监控

 Redis事务的三特性

单独的隔离操作

事务中的所有命令都会被序列化、按顺序的执行,事务在执行的过程中,不会被其他客户端发来的命令请求所打断。

没有隔离级别的概念

 队列中的命令在没有提交前不会实际执行

不保证原子性

食物中如果有一条命令执行失败,其后的命令依然被执行,没有回滚