redis
(八)分布式锁
应用场景:秒杀抢券的业务下,需要使用到分布式锁。
举例:抢券
1.如果不加任何锁,那么多个线程执行的时候,会导致超卖的情况。
2.如果添加了synchronized本地锁,在只有一台服务器运行的情况下,没有问题;但是,一般为了减轻压力,会使用多台服务器,使用nginx反向代理、负载均衡,这种情况下,不同服务器之间使用synchronized就无法生效。此时,可以使用redis的分布式锁。
redis锁是怎样实现的?
Redis实现分布式锁主要利用Redis的setnx命令,(set if not exists)如果不存在则set
获取锁:
SET lock value NX EX 10(添加锁,NX是互斥,EX是设置超时时间)
释放锁:
DEL key(释放锁,删除即可)
流程:
线程执行时,尝试获取锁;获取失败则说明已经有其他线程执行中;获取成功,则执行业务;最后释放锁。
※为何要设置时间EX(假如说不设置时间,如果执行业务过程中,服务器宕机了,那么这个锁将一直存在着,无法被释放;加了时间,则超过时间后会自动释放锁)
Q:Redis实现分布式锁,如何有效控制锁的有效时长?
1、根据业务执行预估(不靠谱)
2、给锁续期,新建一个线程,用来监控执行业务有没有结束,来增加锁的时间(过于繁琐,有现成的方法可以使用-redisson)
Redisson实现的分布式锁
1、有一个watch dog,用来监视
2、线程2如果获取锁失败,会再次循环尝试获取锁,但是是在一定时间内,并不是无限获取。
3、redisson底层是setnx和lua脚本(保持原子性)
redisson实现分布式锁,可重入。
前提:需要判断是不是同一个线程。
原理:使用了hash结构,来记录线程id和重入次数(第一次获得锁,次数为1;子方法中第二次获得锁,次数为2;第二次执行完释放锁,次数为1;第一次再释放锁,次数为0)