[分布式锁的实现文章][1],单点的方式很好理解,但在 redis 集群上会出现问题,如:
- 客户端 A 在主节点获得了一个锁。
- 主节点挂了,而到从节点的写同步还没完成。
- 从节点被提升为主节点。
- 客户端 B 获得和 A 相同的锁
文中描述了 redlock 算法, 获取锁的步奏
- 获取当前时间,以毫秒为单位。
- 以串行的方式尝试从所有的 N 个实例中获取锁,使用的是相同的 key 值和相同的随机 value 值。在从每个实例获取锁时,客户端会设置一个连接超时,其时长相比锁的自动释放时间要短得多。例如,若锁的自动释放时间是 10 秒,那么连接超时大概设在 5 到 50 毫秒之间。这可以避免当 Redis 节点挂掉时,会长时间堵住客户端:如果某个节点没及时响应,就应该尽快转到下个节点。
- 客户端计算获取所有锁耗费的时长,方法是使用当前时间减去步骤 1 中的时间戳。当且仅当客户端能从多数节点(至少 3 个)中获得锁,并且耗费的时长小于锁的有效期时,可认为锁已经获得了。
- 如果锁获得了,它的最终有效时长将重新计算为其原时长减去步骤 3 中获取锁耗费的时长。
- 如果锁获取失败了(要么是没有锁住 N/2+1 个节点,要么是锁的最终有效时长为负数),客户端会对所有实例进行解锁操作(即使对那些没有加锁成功的实例也一样)。
我不是很理解这个算法,假设一个 3 主 3 从的 redis 集群,从描述中看是setnx这个操作要在 6/2+1=4 个节点上操作成功,才认为是获得了锁。在客户端操作 redis 集群的时候可以直接操作到某一节点吗?以上是猜测,可能一开始就错了,有人能指点一下吗?
[1]: http://www.oschina.net/translate/redis-distlock