Curator框架

本文详细介绍了Curator框架中的LeaderLatch和Leader Election两种分布式选主机制,包括创建、删除、读取和更新Zookeeper节点的操作。通过源码分析,揭示了LeaderLatch的抢占式选主过程和Leader Election的公平选举实现,强调了在实际使用中处理连接问题和错误处理的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Curator

Curator中提供了Zookeeper各种应用场景(分布式锁、Master选举机制和分布式计算器等)的抽象封装。
项目组件:

名称 描述
Recipes Zookeeper典型应用场景的实现,这些实现是基于Curator Framework。
Framework Zookeeper API的高层封装,大大简化Zookeeper客户端编程,添加了例如Zookeeper连接管理、重试机制等。
Utilities 为Zookeeper提供的各种实用程序。
Client Zookeeper client的封装,用于取代原生的Zookeeper客户端(ZooKeeper类),提供一些非常有用的客户端特性。
Errors Curator如何处理错误,连接问题,可恢复的例外等。

创建节点
(1)创建一个初始内容为空的节点:client.create().forPath(path); Curator默认创建的是持久节点,内容为空。
(2)创建一个包含内容的节点:client.create().forPath(path,"我是内容".getBytes());
(3)创建临时节点,并递归创建父节点client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(path); 在递归创建父节点时,父节点为持久节点。

删除节点
(1)删除一个子节点client.delete().forPath(path);
(2)删除节点并递归删除其子节点client.delete().deletingChildrenIfNeeded().forPath(path);
(3)指定版本进行删除client.delete().withVersion(1).forPath(path); 如果此版本已经不存在,则删除异常,异常信息如下。
(4)强制保证删除一个节点client.delete().guaranteed().forPath(path); 只要客户端会话有效,那么Curator会在后台持续进行删除操作,直到节点删除成功。比如遇到一些网络异常的情况,此guaranteed的强制删除就会很有效果。

读取数据
读取节点数据内容API相当简单,Curator提供了传入一个Stat,使用节点当前的Stat替换到传入的Stat的方法,查询方法执行完成之后,Stat引用已经执行当前最新的节点Stat。

// 普通查询
client.getData().forPath(path);
// 包含状态查询
Stat stat = new Stat();
client.getData().storingStatIn(stat()).forPath(path);

更新数据
更新数据,如果未传入version参数,那么更新当前最新版本,如果传入version则更新指定version,如果version已经变更,则抛出异常。

// 普通更新
client.setData().forPath(path,"新内容".getBytes());
// 指定版本更新
client.setData().withVersion(1).forPath(path);

版本不一致异常信息:
org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for

异步接口
  在使用以上针对节点的操作API时,我们会发现每个接口都有一个inBackground()方法可供调用。此接口就是Curator提供的异步调用入口。对应的异步处理接口为BackgroundCallback。此接口指提供了一个processResult的方法,用来处理回调结果。其中processResult的参数event中的getType()包含了各种事件类型,getResultCode()包含了各种响应码。重点说一下inBackground的以下接口:public T inBackground(BackgroundCallback callback, Executor executor); 此接口就允许传入一个Executor实例,用一个专门线程池来处理返回结果之后的业务逻辑。

源码分析

LeaderLatch

  LeaderLatch的方式,是以一种抢占的方式来决定选主。类似非公平锁的抢占,所以多节点是一个随机产生主节点的过程。

使用
LeaderLatch创建好之后,必须执行:leaderLatch.start();这样,才能让leaderLatch开始参与选主过程。由于LeaderLatch是一个不断抢占的过程,所以需要调用:public boolean hasLeadership()来检测当前参与者是否选主成功。这个方法是非阻塞的(立即返回),其结果只代表调用时的选主结果。所以,可以轮询此方法,或者当执行完本地逻辑后,需要执行分布式任务前检擦此方法。不过,类似JDK中的CountDownLatch,LeaderLatch也提供了阻塞方法:

public void await()
          throws InterruptedException,
                 EOFException

这个方法,会阻塞,直到选主成功。

方法2 为了避免方法1的长时间选主失败

public boolean await(long timeout,
                     TimeUnit unit)
             throws InterruptedException

这个方法会根据参数中指定的时间,作为等待的期限。到期后,返回选主结果。

对于LeaderLatch实例,无论是否轩主成功,最后都应该调用:
leaderLatch.close();

这样,才会把当前参与者的信息从选主分组中移除出去。如果,当前参与者是主,还会释放主的资格。避免死锁。
4. 错误处理

在实际使用中,必须考虑链接问题引起的主身份丢失问题。 例如:当hasLeadership()返回true,之后链接出问题。 强烈建议:使用LeaderLatch时为其添加一个ConnectionStateListener

LeaderLatch实例会添加一个ConnectionStateListener来监听当前zk链接。 如果,链接不可用(SUSPENDED)则LeaderLatch会认为自己不在是主,等到链接恢复可用时,才可继续。 如果,链接断开(LOST),则LeaderLatch会认为自己不在是主,等到链接重新建立后,删除之前的参与者信息,然后重新参与选主。

成员变量

log : caurtor依赖slf4j
client : zk客户端(curator-framework提供)
latchPath : 分组路径(zk中的path)
id : 参与者ID
state
    内部枚举
    状态
        LATENT 休眠
        STARTED 已启动
        CLOSED 已关闭
    使用AtomicReference原子化包装
hasLeadership
    是否为主
    使用AtomicBoolean原子化包装
ourPath
    使用AtomicReference原子化包装
listeners
    一组LeaderLatchListener监听器
closeMode
    内部枚举
    LeaderLatch关闭方式
        SILENT : 静默关闭,不触发相关监听器
        NOTIFY_LEADER :关闭时触发监听器
startTask
    异步Future
    使用AtomicReference原子化包装
listener
    链接状态监听器
    参见 : 4.</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值