面试题答案
一键面试Redis实现分布式锁的方式
- 基于SETNX命令:SETNX(SET if Not eXists)命令用于在键不存在时设置键的值。如果键已经存在,SETNX不做任何操作。在分布式锁场景中,多个客户端尝试使用SETNX来设置一个特定的锁键,只有第一个成功设置的客户端获得锁。
- 设置过期时间:为了防止持有锁的客户端崩溃而导致锁永远无法释放,需要给锁键设置一个过期时间。可以在SETNX成功后,立即使用EXPIRE命令为键设置过期时间,或者在使用SET命令时直接设置过期时间。
用到的Redis命令
- SETNX key value:尝试设置键的值,仅当键不存在时设置成功,返回1;若键已存在,设置失败,返回0。
- EXPIRE key seconds:为键设置过期时间,以秒为单位。
- SET key value [EX seconds] [PX milliseconds] [NX|XX]:这是一个更通用的命令,其中
EX seconds
用于设置键的过期时间(秒),PX milliseconds
用于设置键的过期时间(毫秒),NX
表示仅当键不存在时才设置键的值,XX
表示仅当键已存在时才设置键的值。
命令协同工作保证原子性
- SETNX和EXPIRE结合(非原子操作):在早期版本中,使用SETNX设置锁键,然后使用EXPIRE设置过期时间。然而,这两个操作不是原子的,如果在SETNX成功后,EXPIRE执行前客户端崩溃,锁将永远不会过期。
- 使用SET命令(原子操作):现代Redis版本支持使用
SET key value EX seconds NX
这样的命令,它将设置值和设置过期时间合并为一个原子操作。这样可以确保在设置锁键的同时设置过期时间,从而保证了锁操作的原子性。多个客户端并发执行这个命令时,只有一个客户端能够成功设置锁键并获得锁,其他客户端将因为键已存在而设置失败,无法获得锁。