redis分布式锁一般不是阻塞锁,如何实现redis分布式阻塞锁?
阻塞的本质是让客户端线程阻塞等待。
服务器是做不到的,redis也是做不到的。
因此,必然是客户端线程获得锁失败后,自己阻塞。但是同时阻塞后需要有人去定期查看分布式锁是否已被释放或者服务器异步通知客户端分布式锁已被释放。一但释放就去抢锁,成功则唤醒客户端线程。
下面提供一个思路:
(1)阻塞和唤醒线程,比如Java则是 LockSupport.park()
和LockSupport.unpark(thread)
。
(2)定期获得锁方式,设计一个同步容器,看是否区分公平或非公平而设置为同步有序,或同步无序容器。客户端阻塞前,将Thread.currentThread()
加入同步容器。固定的一个定时任务去setnx,获得锁,则在同步容器中选择合适的线程,唤醒他,并告诉他获得锁。
(3)唤醒方式也类似增加同步容器。采用pub, sub,固定的线程等待redis发布消息,获得后,唤醒客户端线程,让客户端线程自己去setnx获得锁。但是有个问题,redis并不能自己publish消息,需要进一步实现,比如客户端释放锁后发布消息,存在获得锁的客户端崩溃导致分布式锁过期释放但没人发布锁释放的消息。因此,此类方式只能作为辅助手段。
题外话,既然有阻塞了,相当于线程已经不关注获得锁的性能了,推荐使用zookeeper分布式锁。