一、锁是怎么获取的?
setnx:不存在则设置
或者:SET lock unique_value NX PX 10000;
二、锁是怎么释放的?
在finally代码块中删掉key释放锁
三、怎么避免死锁?
在setnx抢占到锁后,用expire设置过期时间
四、在expire执行前进程挂掉了怎么办?
使用Lua脚本把setnx、expire两个步骤合成一个原子操作。
五、第一个线程任务还没执行完,但它的锁过期时间到了已自动释放掉,此时第二个线程抢到锁开始执行,等第一个线程执行完又释放掉第二个线程加的锁怎么办?
-
针对过期时间到了还没执行完的问题,可以通过守护线程,在锁即将过期前,检查业务是否执行完,若没有则给锁key延长过期时间,Resisson中的「看门狗」自动续时就实现了这个功能。
-
这对释放掉别人加的锁的问题,可以在设置key的,用独特的唯一标识,如uuid作为value,在删除前比较value值是不是当然线程设置的,是则删除。当然要使用Lua脚本把比较、删除两个步骤合成一个原子操作。
六、在Redis集群场景,主从数据不是强一致性情况下,主节点宕机时数据还未来得及复制到从节点,选举出新的主节点后没有之前加的锁,此时新的线程过来还是会加锁成功怎么办?
问题补充说明:
普通的单机redis分布式锁,加锁时只作用在一个redis节点上,即使这个master节点通过哨兵机制实现了高可用,但是当发生故障转移时,主从复制是异步的,推选出来新的master节点可能会没有之前加的锁,这就会导致在故障转移期间可能会有多个客户端获取到锁。
-
RedLock算法
-
超过一半的master节点(N/2+1)获取锁成功才算是加锁成功