分布式锁
是控制分布式系统之间共同访问共享资源的一种锁的实现
分布式锁需要解决的问题
1、互斥性:任意时刻只能有一个客户端获取锁;
2、安全性:锁只能被持有该锁的客户端删除,不能由其他客户端删除;
3、死锁:如果获取锁的客户端出现宕机而未能释放锁,那么其他客户端将再也无法获取到锁而导致死锁;
4、容错:当部分Redis
节点宕机时,客户端仍然能获取锁和释放锁。
由于Redis
为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis
的连接并不存在竞争关系,故利用该特性可实现分布式锁。
利用Redis
的SETNX
命令来实现,由于当某个 key
不存在的时候,SETNX
才会设置该 key
。并且 Redis
采用单进程单线程模型,所以,不需要担心并发的问题。就可以利用 SETNX
的特性维护一个 key
,存在的时候,即锁被某个线程持有;不存在的时候,没有线程持有锁。
至此还有一个问题:如果一个请求获取到了锁,但是在执行时因为某些原因意外退出了,如服务器宕机。导致创建了锁但是没有删除锁,那么这个锁将一直存在,以至于以后缓存再也得不到更新,就是死锁问题。于是我们需要给锁设置一个过期时间以防止这种情况的发生。
因为 ** SetNX
** 不具备设置过期时间的功能,所以我们需要借助 Expire
来设置,同时我们需要把两者放在一个事务中,以确保请求的原子性,以免 SetNX
成功了 Expire
却失败了,并且只有在获取到锁时才设置过期时间。