Zookeeper实战-使用Curator实现Leader选举

分布式系统中,对于一个复杂的任务,我们经常会选举一个Master节点,借助zk我们可以轻易的实现此项任务,在kafka以及spark的standalone模式下都是使用zk来实现Master选举,本文先从原理方面介绍为什么zk可以实现Master选举,然后利用curator的api进行Master选举实战。

zk进行Master选举原理

zookeeper的节点有两种类型: 持久节点和临时节点。临时节点有个非常重要的性质,如果注册这个节点的机器失去连接,那么这个节点会被zookeeper删除。选主过程就是利用这个特性,在服务器启动的时候,去zookeeper特定的一个目录下注册一个临时节点(这个节点作为master,谁注册了这个节点谁就是master),注册的时候,如果发现该节点已经存在,则说明已经有别的服务器注册了(也就是有别的服务器已经抢主成功),那么当前服务器只能放弃抢主,作为从机存在。同时,抢主失败的当前服务器需要订阅该临时节点的删除事件,以便该节点删除时(也就是注册该节点的服务器宕机了或者网络断了之类的)进行再次抢主操作。Maser选举的过程,其实就是简单的争抢在zookeeper注册临时节点的操作,谁注册了约定的临时节点,谁就是master

Master选举实战

curator对原生api进行了封装,将节点创建,时间监听和自动选举过程进行了封装,我们只需要调用API即可实现Master选举。本文分别使用LeaderSelector和LeaderLatch两种方式,进行server模拟真实的运行场景。

LeaderSelector

LeaderSelector是利用Curator中InterProcessMutex分布式锁进行抢主,抢到锁的即为Leader。

  1. LeaderSelector

    org.apache.curator.framework.recipes.leader.LeaderSelector
    //开始抢主
    void start()
    //在抢到leader权限并释放后,自动加入抢主队列,重新抢主
    void autoRequeue()
    
  2. LeaderSelectorListener是LeaderSelector客户端节点成为Leader后回调的一个监听器,在takeLeadership()回调方法中编写获得Leader权利后的业务处理逻辑。

    `org.apache.curator.framework.recipes.leader.LeaderSelectorListener`
    //抢主成功后的回调
    void takeLeadership()
    
  3. LeaderSelectorListenerAdapter是实现了LeaderSelectorListener接口的一个抽象类,封装了客户端与zk服务器连接挂起或者断开时的处理逻辑(抛出抢主失败CancelLeadershipException),一般监听器推荐实现该类

Server

我们模拟的server继承LeaderSelectorListenerAdapter,该监听器会在获取到Master权利时候回调改监听器,执行takeLeadership方法,在这里我们只打印改server的名字,当一个实例成为Master后,其他实例会进入等待,直到当前Master挂了或者退出后才会进行新的选举。

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;

import java.io.Closeable;

public class Server extends LeaderSelectorListenerAdapter implements Closeable {
   
   
    /** server name **/
    private final String serverName;

    /** listener */
    private final LeaderSelector leaderSelector;

    /** takeLeadership方法中设置线程阻塞多长时间,单位ms */
    private final int SLEEP_MILLISECOND = 100000;

    public Server(CuratorFramework client, String path, String serverName) {
   
   
        this.serverName = serverName;
        /** client, zk-path, listener */
        leaderSelector = new LeaderSelector(client, path, this);
        /** 允许多次参与选主**/
        leaderSelector.autoRequeue();
    }

    public void start() {
   
   
        leaderSelector.start();
        System.out.println(getServerName() + "开始运行了!");
    }

    @Override
    public void close() {
   
   
        leaderSelector.close();
        System.out.println(getServerName() + "释放资源了!");
    }

    @Override
    public void takeLeadership(CuratorFramework client) {
   
   
        try {
   
   
            System.out.println(getServerName() + "是Master, 执行到takeLeadership()方法了!")
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值