一个简单的基于Zookeeper实现主从选举的例子

    生产环境中一般都要实现高可用,保证集群中其中一个节点down掉之后,集群还能正常运行,并且有些业务只能在主节点上运行,其他节点只是处于备用状态。

    项目中的高可用是基于Zookeeper实现,采用的是主从方式,一台节点作为Master,另外几台节点作为Slave。实际使用ZK开发的话,一般会使用Curator框架,它是由Netflix公司贡献给Apache的,主要是封装了ZK的客户端,方便开发人员的使用。本文基于ZK写了一个高可用的简单Demo。

 

基于Curator的选主策略:

    有两种选主策略:LeaderLatch 和 LeaderSelector。

    LeaderLatch采用的是抢占的方式来选主(非公平),一旦选出Leader,除非有客户端挂掉重新触发选举或者主动调用close()方法,否则不会交出Leadership。

    LeaderSelector则是每个客户端都能公平获取Leadership,但是选举出来的Leader不会一直占用领导权,当takeLeadership()方法结束后就会自动释放领导权。

    综上可以得出,LeaderLatch更加适合HA这种方式,本文后续分析的就是此种方法,LeaderSelector后续用到了再说。

 

LeaderLatch方式选举主节点:

图示如下:

 

    创建的是Ephemeral + Sequence节点。

    Ephemeral节点如果创建它的客户端和服务器之间的Session结束会被自动删除。(Persist节点则不会)。

    Sequence节点则是多个客户端创建同一名称节点时,都会创建成功,只是节点名称后面会跟上0,1,2,3这样的序号(Non-Sequence节点则是当多个客户端创建同一个Non-Sequence节点时,只有一个可以创建成功,并且节点名称可创建时指定的节点名称完全一样)。

 

基于SpringBoot实现的一个小Demo:

 
@SpringBootApplication
public class SpringBootApplicationDemo1 {

    //todo 这个类不能直接放到src目录下面
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplicationDemo1.class, args);
        LeaderLatchContext.INSTANCE.startLeaderLatch();
    }

}
public class LeaderLatchContext {

    public static final LeaderLatchContext INSTANCE = new LeaderLatchContext();

    //主节点竞争客户端初始化标识(服务器刚部署的时候才用到这个属性)
    private boolean leaderLatchInitedInd = false;


    /**
     * 主节点竞争类
     */
    private LeaderLatch leaderLatch;

    /**
     * 主节点竞争时给竞争客户端用
     */
    private CuratorFramework zkClient = ZookeeperUtil.getClient("10.10.23.37:2181");

    /**
     * 主节点竞争路径
     */
    private static final String latchPath = "/leaderlatch";

    /**
     * 基于ZK进行主从节点选举(主节点挂了之后,其他节点能切换过来,但是时间有点长)
     */
    public void startLeaderLatch() {

        //防止主从之间来回切换
        Lock lock = new ReentrantLock();

        if (!leaderLatchInitedInd) {
            //初始化竞争类
            //LeaderLatch.CloseMode.NOTIFY_LEADER: When the latch is closed, listeners *will* be notified
            leaderLatch = new LeaderLatch(zkClient, latchPath, "123456789", LeaderLatch.CloseMode.NOTIFY_LEADER);
            //加入监听机制
            leaderLatch.addListener(new LeaderLatchListener() {
                @Override
                public void isLeader() {
                    try {
                        lock.lock();
                        System.out.println("=========================================I am Leader=========================================");
                        System.out.println(leaderLatch.getId());
                    } finally {
                        lock.unlock();
                    }
                }

                @Override
                public void notLeader() {
                    try {
                        lock.lock();
                        System.out.println("=========================================I am not Leader=========================================");
                        System.out.println(leaderLatch.getId());
                    } finally {
                        lock.unlock();
                    }
                }
            });

            //开始主节点竞争
            try {
                leaderLatch.start();
            } catch (Exception e) {
                System.out.println("Leader Latch start error");
                e.printStackTrace();
            }

            leaderLatchInitedInd = true;

        } else {
            System.out.println("Leader has already init.");
        }


    }

}

后续有时间再好好探究一下ZK内部的原理…感觉遗留了好多坑没时间填,慢慢填吧

 

 

 

参考:

    http://ifeve.com/zookeeper-leader/(学习Zookeeper的Leader选举)

   https://blog.csdn.net/qq_34021712/article/details/82880062(Zookeeper的两种选举方式图示)

    https://segmentfault.com/a/1190000016072834(基于ZK的分布式锁)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值