ZooKeeper之Curator分布式锁和Leader选举实例

分布式锁

分布式编程时,当遇到应用程序多机部署,于是当多个应用同时访问某一资源时,就需要某种机制去协调它们进行占用。例如,现在一台应用正在rebuild缓存内容,要临时锁住这个区域暂时不让其它应用进行访问;又比如调度程序每次只想一个任务被一台应用执行等等业务场景。

下面的程序会启动两个线程x1和x2去争夺锁,拿到锁的线程会占用10秒。运行多次可以观察到,有时是x1先拿到锁而x2等待,有时又会反过来。Curator会用我们提供的lock路径的结点作为全局锁,这个结点的数据类似这种格式:[_xxxxxx-lock-0000000005],每次获得锁时会生成这种串,释放锁时清空数据。


import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.RetryNTimes;

import java.util.concurrent.TimeUnit;

/**
 * @Title: Spring-distributed
 * @Description:
 * @author: liaryank
 * @Date: 2020/5/7 1:32 下午
 * @Version: 1.0
 */
public class CuratorLock {
    /** Zookeeper info 可以写上端口如果是默认的不写也可以,写就就是192.168.3.32:2181,xxx*/
    private static final String ZK_ADDRESS = "192.168.3.32,192.168.3.33,192.168.3.34";
    private static final String ZK_LOCK_PATH = "/zklocktest";

    public static void main(String[] args) throws InterruptedException {
        // 1.Connect to zk
        CuratorFramework client = CuratorFrameworkFactory.newClient(
                ZK_ADDRESS,
                //设置数量和释放时间
                new RetryNTimes(10, 10000)
        );
        client.start();
        System.out.println("zookeeper-client-start=>ok!");

        Thread x1 = new Thread(() -> {
            doWithLock(client);
        }, "x1");
        Thread x2 = new Thread(() -> {
            doWithLock(client);
        }, "x2");

        t1.start();
        t2.start();
    }

    private static void doWithLock(CuratorFramework client) {
        InterProcessMutex lock = new InterProcessMutex(client, ZK_LOCK_PATH);
        try {
            if (lock.acquire(10 * 1000, TimeUnit.SECONDS)) {
                System.out.println(Thread.currentThread().getName() + " holdlock");
                Thread.sleep(5000L);
                System.out.println(Thread.currentThread().getName() + " releaselock");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                lock.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Leader选举 

当集群里的某个服务宕机或故障时,我们可能要从follower结点里选出一个作为新的master,这时就需要能在分布式环境中自动协调的Leader选举方法。Curator提供了LeaderSelector监听器实现Leader选举功能。同时,只有一个Listener会进入takeLeadership()方法,说明它是当前的Leader。

当Listener从takeLeadership()退出时就说明它放弃了“Leader身份”,这时Curator会利用Zookeeper再从剩余的Listener中选出一个新的Leader。autoRequeue()方法使放弃Leadership的Listener有机会重新获得Leadership,如果不设置的话放弃了的Listener是不会再变成Leader的 


import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListener;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.curator.retry.RetryNTimes;
import org.apache.curator.utils.EnsurePath;
/**
 * @Title: Spring-distributed
 * @Description:
 * @author: liaryank
 * @Date: 2020/5/7 3:50 下午
 * @Version: 1.0
 */
public class CuratorLeader {

    /** Zookeeper info 可以写上端口如果是默认的不写也可以*/
    private static final String ZK_ADDRESS = "192.168.3.32,192.168.3.33,192.168.3.34";
    private static final String ZK_PATH = "/zklocktest";

    public static void main(String[] args) throws InterruptedException {
        LeaderSelectorListener listener = new LeaderSelectorListener() {
            @Override
            public void takeLeadership(CuratorFramework client) throws Exception {
                System.out.println(Thread.currentThread().getName() + " take=》leadership!");
                Thread.sleep(5000L);

                System.out.println(Thread.currentThread().getName() + " relinquish=》leadership!");
            }

            @Override
            public void stateChanged(CuratorFramework client, ConnectionState state) {
            }
        };

        new Thread(() -> {
            registerListener(listener);
        }).start();

        new Thread(() -> {
            registerListener(listener);
        }).start();

        new Thread(() -> {
            registerListener(listener);
        }).start();

        Thread.sleep(Integer.MAX_VALUE);
    }

    private static void registerListener(LeaderSelectorListener listener) {
        CuratorFramework client = CuratorFrameworkFactory.newClient(
                ZK_ADDRESS,
                new RetryNTimes(10, 10000)
        );
        client.start();

        //Ensure path
        try {
            new EnsurePath(ZK_PATH).ensure(client.getZookeeperClient());
        } catch (Exception e) {
            e.printStackTrace();
        }

        //Register listener
        LeaderSelector selector = new LeaderSelector(client, ZK_PATH, listener);
        selector.autoRequeue();
        selector.start();
    }
}

 就先写到这里~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值