分布式锁实现
为什么要有分布式锁
正如上一篇说到的,在集群环境下,你在写业务代码时很有可能需要保证某一个变量的安全,这是单靠juc中的工具类已经不够了,因为不是同一个内存,物理机是隔绝的,这时候怎么办?需要使用分布式锁,通过redis、zookeeper或者数据库等共享的存储作为锁相关存放的空间。
分布式锁需要满足的条件
分布式锁需要满足的条件与单机锁都是一样的,互斥性、重入性、阻塞性、公平性、读写锁,当然不是需要同时满足,但是最起码是可扩展的。
互斥性:就是指同一时间在集群中只有一个进程中的一个线程能够持有这把锁,其他的任何线程中不能持有。
重入性:重入性对于一把锁来说还是非常重要的,首先重入性指的是当一个线程拿到这把锁之后,当前线程还可以再次获取这把锁,甚至多次重复获取。避免死锁。
阻塞性:在JUC中AQS已经帮我们做好了相关的处理,第二个、第三个线程没获取到锁的时候,在队列上排队等待,然后持有锁的线程执行完之后会通知队列头部的线程获取锁执行,也叫LeaderFollower模式。分布式锁的阻塞性怎么实现,while循环(手动哭笑)。下文详说。
公平性:锁的公平性是指,公平锁,先来后到,对吧,大家都在队列上等着,先后很明确。非公平锁,我来了,我要跟队列头部去竞争,我俩谁拿到谁就有权利,你们都一边儿呆着去,就是牛逼,这就是非公平锁。
读写锁:对一个变量的读和写用两把锁控制,互不影响。
大概的这些名词释义我们写完了,接下来写具体怎么实现。
redis实现分布式锁
redis实现分布式锁也是比较简单的,但是也比较麻烦,就看细不细。
都知道是使用setNX命令
1、返回1就是上锁成功继续往下执行,返回0就是上锁失败,这时候就要选择策略了,是放弃啊还是继续重试,还是像AQS那样安排一个队列放上去。
2、要注意超时时间的设定,无论是setnx的操作时间,还是上锁之后的自动解锁时间,都得设置,不然一旦发生死锁,导致的整个系统不可用。
3、注意一个问题,在极高的并发的场景下同时为了稳定考虑,如果redis是集群模式部署,又得采用RedLock锁,因为我们都知道,redis的集群模式下,数据的修改是从主节点写入的,但是读却是可以从节点读,所以为了数据的绝对准确我们需要采用红锁的方式进行上锁。
我们直接看一下redssion的实现吧