Curator实现分布式锁的基本原理-getTheLock

// From StandardLockInternalsDriver 
public PredicateResults getsTheLock(CuratorFramework client, List<String> children, String sequenceNodeName, int maxLeases) throws Exception{ 
	// 之前创建的临时顺序节点在排序后的子节点列表中的索引 
	int ourIndex = children.indexOf(sequenceNodeName); 
	// 校验之前创建的临时顺序节点是否有效 
	validateOurIndex(sequenceNodeName, ourIndex); 
	// 锁公平性的核心逻辑 
	// 由InterProcessMutex的构造函数可知,maxLeases为1,即只有ourIndex为0时,线程才能持有锁,或者说该线程创建的临时顺序节点激活了锁 
	// Zookeeper的临时顺序节点特性能保证跨多个JVM的线程并发创建节点时的顺序性,越早创建临时顺序节点成功的线程会更早地激活锁或获得锁 
	boolean getsTheLock = ourIndex < maxLeases; 
	// 如果已经获得了锁,则无需监听任何节点,否则需要监听上一顺序节点(ourIndex-1) 
	// 因为锁是公平的,因此无需监听除了(ourIndex-1)以外的所有节点,这是为了减少羊群效应,非常巧妙的设计!! 
	String pathToWatch = getsTheLock ? null : children.get(ourIndex - maxLeases); 
	// 返回获取锁的结果,交由上层继续处理(添加监听等操作) 
	return new PredicateResults(pathToWatch, getsTheLock); 
} 

static void validateOurIndex(String sequenceNodeName, int ourIndex) throws KeeperException{ 
	if ( ourIndex < 0 ){ 
		// 容错处理,可跳过 
		// 由于会话过期或连接丢失等原因,该线程创建的临时顺序节点被Zookeeper服务端删除,往外抛出NoNodeException 
		// 如果在重试策略允许范围内,则进行重新尝试获取锁,这会重新重新生成临时顺序节点 
		// 佩服Curator的作者将边界条件考虑得如此周到! 
		throw new KeeperException.NoNodeException("Sequential path not found: " + sequenceNodeName); 
	} 
}

猜你喜欢

转载自blog.csdn.net/Leon_Jinhai_Sun/article/details/112853439