Redis SETNX命令实现分布式锁工作原理
- 基本原理:SETNX(SET if Not eXists)命令用于在指定的键不存在时,为键设置指定的值。在分布式锁场景中,多个客户端尝试使用SETNX命令来设置同一个键的值(通常为一个唯一标识,如UUID)。只有一个客户端能够成功设置,这个客户端就获得了锁。
- 原子性操作:Redis的SETNX命令是原子性的。这意味着在Redis服务器端,该操作要么完全执行成功,要么完全不执行。在多客户端并发尝试获取锁时,不会出现两个客户端同时成功设置键值的情况。例如,假设有客户端A和客户端B同时执行SETNX lock_key unique_value,Redis内部保证只会有一个客户端的操作生效。
- 防止锁被误释放:
- 使用唯一标识:在获取锁时,每个客户端设置的value应该是唯一的,比如使用UUID。当释放锁时,首先获取锁对应的value,只有value与自己设置的唯一标识相匹配时才执行删除操作。这样可以避免一个客户端释放了其他客户端获取的锁。
- Lua脚本:可以使用Lua脚本来确保释放锁操作的原子性。例如,下面的Lua脚本:
if redis.call("GET",KEYS[1]) == ARGV[1] then
return redis.call("DEL",KEYS[1])
else
return 0
end
客户端在执行释放锁操作时,通过Redis的EVAL命令执行这个Lua脚本,传入锁的键名和自己设置的唯一标识。这样可以保证在判断锁的持有者和删除锁这两个操作之间不会被其他客户端干扰,从而有效防止误释放锁。