关于代码的疑问

来源: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回答

大能老师

2022-10-07

同学你好,代码里面的 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 来保证锁路径的唯一。

0
1
Billy16
大致明白了,谢谢老师解答
2022-10-07
共1条回复

大能老师

2022-10-07

0
0

Java分布式架构设计与开发实战

项目贯穿式讲解,真正将理论与实战相结合

325 学习 · 74 问题

查看课程