Tag Archives: 并发

用Redis实现分布式锁

Redis有一系列的命令,特点是以NX结尾,NX是Not eXists的缩写,如SETNX命令就应该理解为:SET if Not eXists。这系列的命令非常有用,这里讲使用SETNX来实现分布式锁。 用SETNX实现分布式锁 利用SETNX非常简单地实现分布式锁。例如:某客户端要获得一个名字foo的锁,客户端使用下面的命令进行获取: SETNX lock.foo <current Unix time + lock timeout + 1>  如返回1,则该客户端获得锁,把lock.foo的键值设置为时间值表示该键已被锁定,该客户端最后可以通过DEL lock.foo来释放该锁。  如返回0,表明该锁已被其他客户端取得,这时我们可以先返回或进行重试等对方完成或等待锁超时。 解决死锁 上面的锁定逻辑有一个问题:如果一个持有锁的客户端失败或崩溃了不能释放锁,该怎么解决?我们可以通过锁的键对应的时间戳来判断这种情况是否发生了,如果当前的时间已经大于lock.foo的值,说明该锁已失效,可以被重新使用。 发生这种情况时,可不能简单的通过DEL来删除锁,然后再SETNX一次,当多个客户端检测到锁超时后都会尝试去释放它,这里就可能出现一个竞态条件,让我们模拟一下这个场景:  C0操作超时了,但它还持有着锁,C1和C2读取lock.foo检查时间戳,先后发现超时了。  C1 发送DEL lock.foo  C1 发送SETNX lock.foo 并且成功了。  C2 发送DEL lock.foo  C2 发送SETNX lock.foo 并且成功了。 这样一来,C1,C2都拿到了锁!问题大了! 幸好这种问题是可以避免D,让我们来看看C3这个客户端是怎样做的: … Continue reading

Posted in 技术 | Tagged , , , | 12 Comments