回答
SETNX
是 "SET if Not eXists" 的缩写,它所表达的意思是只有在 key 不存在时才设置值。它能够实现分布式锁的主要原因有两点:
- Redis 单线程保证 SETNX 的原子性:
SETNX
是 Redis 中的一个命令,Redis 中的命令执行都是原子性的,这就保证了SETNX
在执行过程中是不会被其他命令打断的。当我们使用SETNX
设置一个 key 时,如果这个 key 已经存在,SETNX
将不会执行任何操作并返回 0;如果这个 key 不存在,它将设置 key的值并返回 1。 - 独占性:
SETNX
的语义是"SET if Not eXists"。这就意味着如果某个客户端成功使用SETNX
设置了一个 key,那么在这个键过期或被删除之前,其他客户端是不可以再次使用SETNX
成功设置相同的 key。这就实现了锁的独占性,确保了在分布式系统中,同一时刻只有一个客户端可以获得锁。
SETNX
的优点在于它实现分布式锁的逻辑很简单,容易理解和实现。同时使用 Redis 的基本特性,保证了加锁的正确性,同时性能较好。
但是,SETNX
的缺点则更加明显:
- 锁无法续期:若获取锁的业务逻辑执行时间比较长,超过了锁的过期时间,则可能会导致锁被提前释放而产生系统风险。
- 无法可重入:同一个线程无法多次重复获取同一把锁。
- 可能会产生死锁:在
SETNX
和设置过期时间(如使用EXPIRE
命令)之间,如果服务器宕机或操作未能成功完成,可能导致锁永久存在,造成死锁。
所以,如果我们想要一个功能比较完善的分布式锁,则可以使用 Redisson 来实现分布式锁: