六、Redis事务控制
1. 事务的概念
定义:Redis执行指令过程中,多条连续执行的指令基本操作,比如:干扰,打断,插队
2. 事务的基本操作
(1)开启事务
multi
作用:设定事务的开启位置,此指令执行后,后续的所有指令均加入到事务中
2)执行事务
exec
作用:设定事务的结束位置,同时执行事务。与multi成对出现,成对使用
注意:加入事务的命令暂时进入到任务队列中,并没有立即执行,只有执行exec命令才开始执行
(3)取消事务
discard
作用:终止当前事务的定义,发生在multi之后,exec之前
(4)事务的工作流程
(5)事务的注意事项
(6)手动进行事务回滚
如何实现redis事务?
首先开启事务(multi),后面存储的数据都存入命令队列中,watch
为开启事务
执行之前的key的值提供监控(乐观锁)的功能,如果key的值变化了,就会放弃事务的执行,最后执行事务(exec)将这个事务提交给服务器执行,自动unwatch(取消对所有 key 的监视)
3. 锁
(1)基于特定条件的事务执行
业务场景:
天猫双11热卖过程中,对已经售罄的货物追加补货,4个业务员都有权限进行补货。
key 添加监视锁,在执行exec前如果key发生了变化,终止事务执行
watch key1 [key2……]
取消对所有 key 的监视
unwatch
【分布式锁】
概念:分布式锁是控制分布式系统之间同步访问共享资源的一种方式
如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。
分布式锁实现的三个核心要素:
加锁:
最简单的方法是使用 setnx 命令。key 是锁的唯一标识,按业务来决定命名。比如想要给一种商品的秒杀活动加锁,可以给 key 命名为 “lock_sale_商品ID” 。而 value 设置成什么呢?我们可以姑且设置成 1。
setnx lock_sale_商品ID 1
当一个线程执行 setnx
返回 1
,说明 key
原本不存在,该线程成功得到了锁;当一个线程执行 setnx
返回 0
,说明 key
已经存在,该线程抢锁失败。
解锁:
有加锁就得有解锁。当得到锁的线程执行完任务,需要释放锁,以便其他线程可以进入。释放锁的最简单方式是执行 del
指令,伪代码如下:
del lock_sale_商品ID
释放锁之后,其他线程就可以继续执 行 setnx
命令来获得锁。
锁超时:
超时是什么意思呢?如果一个得到锁的线程在执行任务的过程中挂掉,来不及显式地释放锁,这块资源将会永远被锁住(死锁),别的线程再也别想进来。所以,setnx 的 key 必须设置一个超时时间,以保证即使没有被显式释放,这把锁也要在一定时间后自动释放。setnx 不支持超时参数,所以需要额外的指令,伪代码如下:
expire lock_sale_商品ID 30