1、分布式锁
redission开源框架
2、加锁机制
当客户端加锁请求进来,redisson会根据hash算法选择一个节点(如果是集群的话)的主节点,也就是只选择集群里的一台机器。
随后向这台节点发送一段lua表达式(将一大堆复杂业务逻辑封装在lua表达式可以保证业务逻辑执行的原子性)。
加锁代码逻辑:先判断锁是否已经存在,不存在则设置锁(锁会存当前客户端的id),然后设置超时时间默认30秒。
3、锁互斥机制
当客户端1已经拿到锁了,客户端2进来后会去判断锁是否已经存在,发现锁已经存在了
再判断锁里存的客户端id是否包含客户端2,很明显锁里存的是客户端1的id
于是返回该锁剩余的时间,之后客户端2会进入一个while循环,一直尝试获取锁。
4、看门狗
每隔10秒会检查客户端是否还持有锁,如有则延长时间将超时时间重新设为30秒。
这样可以保证客户端能一直持有锁,同时如果因为客户端宕机锁也会自动释放
解决了两个场景:
1)设置超时时间,执行者无法判断到底业务逻辑时间会需要执行多少时间,如果设置短了就会导致
业务逻辑没执行完锁释放了
2)不设置超时时间,如果客户端执行过程中宕机了导致没有调用unlock,锁就一直释放不了
5、可重入锁
当客户端1已经拿到锁了,因为业务逻辑客户端1再次进来后会去判断锁是否已经存在,发现锁已经存在了
再判断锁里存的客户端id是否包含客户端1,很明显锁里存的是客户端1的id
于是将锁里存的加锁次数加1
6、释放锁机制
unlock()方法会将锁里存的加锁次数减1,减到0时删除掉锁,即解锁
7、存在的问题
客户端1请求加锁,节点1接受到加锁命令,这时因为意外原因节点1宕机且刚好还没有将加锁信息同步到其他节点
客户端2请求加锁,节点2变成主节点发现没有锁信息,加锁成功。结果导致了两个客户端都获得了锁。