【附源码】使用 ZooKeeper 实现分布式队列、分布式锁和选举详解!

}

}

}

private Map<Long, String> orderedChildren(Watcher watcher) throws KeeperException, InterruptedException {

Map<Long, String> orderedChildren = new TreeMap<>();

List childNames;

childNames = zookeeper.getChildren(dir, watcher);

for (String childName : childNames) {

try {

if (!childName.regionMatches(0, prefix, 0, prefix.length())) {

LOG.warn(“Found child node with improper name: {}”, childName);

continue;

}

String suffix = childName.substring(prefix.length());

Long childId = Long.parseLong(suffix);

orderedChildren.put(childId, childName);

} catch (NumberFormatException e) {

LOG.warn(“Found child node with improper format : {}”, childName, e);

}

}

return orderedChildren;

}

3)、remove方法

public class DistributedQueue {

public byte[] remove() throws NoSuchElementException, KeeperException, InterruptedException {

Map<Long, String> orderedChildren;

while (true) {

try {

//获取所有排好序的子节点

orderedChildren = orderedChildren(null);

} catch (KeeperException.NoNodeException e) {

throw new NoSuchElementException();

}

if (orderedChildren.size() == 0) {

throw new NoSuchElementException();

}

//移除队头节点

for (String headNode : orderedChildren.values()) {

String path = dir + “/” + headNode;

try {

byte[] data = zookeeper.getData(path, false, null);

zookeeper.delete(path, -1);

return data;

} catch (KeeperException.NoNodeException e) {

//另一个客户端已经移除了队头节点,尝试移除下一个节点

}

}

}

}

2、分布式锁


1)、排他锁

排他锁的核心是如何保证当前有且仅有一个事务获取锁,并且锁被释放后,所有正在等待获取锁的事务都能够被通知到

定义锁

通过在ZooKeeper上创建一个子节点来表示一个锁,例如/exclusive_lock/lock节点就可以被定义为一个锁

获取锁

在需要获取排他锁时,所有的客户端都会试图通过调用create()接口,在/exclusive_lock节点下创建临时子节点/exclusive_lock/lock。ZooKeeper会保证在所有的客户端中,最终只有一个客户能够创建成功,那么就可以认为该客户端获取了锁。

同时,所有没有获取到锁的客户端就需要到/exclusive_lock节点上注册一个子节点变更的watcher监听,以便实时监听到lock节点的变更情况

释放锁

/exclusive_lock/lock是一个临时节点,因此在以下两种情况下,都有可能释放锁

  • 当前获取锁的客户端机器发生宕机,那么ZooKeeper上的这个临时节点就会被移除

  • 正常执行完业务逻辑后,客户端就会主动将自己创建的临时节点删除

无论在什么情况下移除了lock节点,ZooKeeper都会通知所有在/exclusive_lock节点上注册了子节点变更watcher监听的客户端。这些客户端在接收到通知后,再次重新发起分布式锁获取,即重复获取锁过程。推荐“Java精选面试题”小程序,内涵 3000+ 道面试题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值