关于代码的疑问
来源:9-6 ZooKeeper分布式锁解决惊群效应的代码实现

Billy16
2022-10-07
老师,关于 zookeeper 的分布式锁的代码有疑问,希望能够解答
如果服务器是集群,currentPath 存的是 lockPath + “/” + Thread.currentThread().getName(),但相同业务的集群,每个服务器的线程有可能重复,比如支付模块:服务器A线程xx 和 服务器B线程xx 的 currentPath 名字可能重复。
情况一:ZooKeeper 中假设 服务器A线程xx 加了锁,之后删除了锁,不会造成服务器B线程xx 可能永远无法获取锁的情况出现
情况二,因为 ZooKeeper 中 服务器A线程xx 已经加入节点数据,服务器B线程xx 调用:zkClient.createEphemeralSequential(lockPath + “/”, Thread.currentThread().getName()); 会抛出异常
这些代码有考虑到吗?还是我看漏了?
2回答
-
同学你好,代码里面的 trylock 是根据 lockPath 来保证唯一性的。
```java
@Override
public boolean tryLock() {
// zkClient.createEphemeral(lockPath, Thread.currentThread().getName());
// 现在就不是看谁先能创建这个临时节点了是吧
// 现在要去创建一个临时的顺序节点,然后看它是不是排在队伍的最前面,对应到zookeeper的节点里面,就是顺序节点里面序号最小的
if(StringUtils.isBlank(currentPath.get())) {
String path = zkClient.createEphemeralSequential(lockPath + "/", Thread.currentThread().getName());
System.out.println("currentPath : " + path);
currentPath.set(path);
}
// 获取到所有的子节点
List<String> children = zkClient.getChildren(lockPath);
Collections.sort(children);
if (StringUtils.equals(currentPath.get(), lockPath + "/" + children.get(0))) {
return true;
} else {
// 计算出它的前一个节点是哪位,这里只能通过下标去获取,不能直接通过节点的顺序号来减一,因为中间可能会跳过一些
// 所以首先我们算出来当前的节点是在哪个下标,然后再做一个 -1 ,得到一个新的下标
int currentIndex = children.indexOf(currentPath.get().substring(lockPath.length() + 1));
String path = lockPath + "/" + children.get(currentIndex - 1);
previousPath.set(path);
}
return false;
}
```
这里的` String path = zkClient.createEphemeralSequential(lockPath + "/", Thread.currentThread().getName());`第一个参数是 lockPath,第二个参数是设置临时节点的值,实际上值我们是不用管的,并不是通过值来保证锁的唯一性的。
如果是生产环境,我们一般建议根据相应的业务规则来保证锁的唯一性。比如:下单可以使用`路径前缀+订单号`作为 lockPath 来保证锁路径的唯一。
012022-10-07 -
大能老师
2022-10-07
00
相似问题