释放锁的操作需要调用 get 方法,然后 if 语句进行判断,判断 OK 然后调用 del 删除,而这三步并不是原子性的
假设线程 A 调用 set 方法设置 key 对应的 value 为 AA 成功, 则线程 A 获取到了锁,然后在执行完业务逻辑后,首先通过 get 方法获取 key 对应的 value,然后通过 if 语句判断为 true,假设在执行 del 方法前对应的 key 已经超时了,并且线程 B 调用 set 方法设置 key 对应的 value 为 BB 成功了,也就是线程 B 获取到了锁,但是这时候线程 A 开始执行 del 方法了,则会把线程 B 对应的 key 的值删除了(不同线程调用 set 的时候 key 一样),也就是释放了锁,这时候其他线程就会竞争到该锁
解决方案
Redis 有一个叫做 eval 的函数,支持 Lua 脚本执行,并且能够保证脚本执行的原子性
if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end