zookeeper学习(3)--实现分布式锁

1、实现原理
zookeeper实现分布式锁的原理为:
(1)每个客户端在/node节点下创建临时的有序节点(临时节点一旦断开连接即会被删除,而有序节点,则序号靠前的节点先获得锁)。
(2)每个客户端都会去判断自己是不是排序最前的那个锁节点,如果是第一个,则获得锁,如果不是,则监控前一个节点的变化,若前一个节点对应的客户端执行完毕或节点因连接中断等被删除,释放锁后,即此客户端再次监听自己是否是排序最前的节点。
这样做可以确保顺序执行,这是一个公平锁,而且每个客户端只用监听前一个客户端对应的节点。

2、实现方式–框架Curator

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import java.util.concurrent.Executors;

public class CuratorTest {

    private static RetryPolicy retryPolicy  = new ExponentialBackoffRetry(1000,3);
    private static CuratorFramework client = CuratorFrameworkFactory.builder()
            .connectString("hadoop1:2181,hadoop2:2181,hadoop3:2181")
            .sessionTimeoutMs(3000)
            .connectionTimeoutMs(5000)
            .retryPolicy(retryPolicy)
            .build();

    public static void main(String[] args) throws Exception{
        /**
         * 创建会话
         * */
        client.start();

        /**
         * 同步创建节点
         * 注意:
         *      1.除非指明创建节点的类型,默认是持久节点
         *      2.ZooKeeper规定:所有非叶子节点都是持久节点,所以递归创建出来的节点,
         *          只有最后的数据节点才是指定类型的节点,其父节点是持久节点
         * */

        //创建一个初始内容为空的节点
        client.create().forPath("/China");
        //创建一个初始内容不为空的节点
        client.create().forPath("/Korea","jinzhengen".getBytes());
        //创建一个初始内容为空的临时节点
        client.create().withMode(CreateMode.EPHEMERAL).forPath("America");
        //创建一个初始内容不为空的临时节点,可以实现递归创建
        client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL)
                .forPath("Japan","xiaoriben".getBytes());


        /**
         *  异步创建节点
         *
         * 注意:如果自己指定了线程池,那么相应的操作就会在线程池中执行,如果没有指定,
         *   那么就会使用Zookeeper的EventThread线程对事件进行串行处理
         * */
        client.create().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("当前线程:" + Thread.currentThread().getName() + ",code:"
                + event.getResultCode() + ",type:" + event.getType());
            }
        },Executors.newFixedThreadPool(10)).forPath("/async-China");


        client.create().withMode(CreateMode.EPHEMERAL).inBackground(new BackgroundCallback() {
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("当前线程:" + Thread.currentThread().getName() + ",code:"
                        + event.getResultCode() + ",type:" + event.getType());
            }
        }).forPath("/async-America");

        /**
         * 获取节点内容
         * */
        byte[] data = client.getData().forPath("/Korea");
        System.out.println(new String(data));
        //传入一个旧的stat变量,来存储服务端返回的最新的节点状态信息
        byte[] data2 = client.getData().storingStatIn(new Stat()).forPath("/Korea");
        System.out.println(new String(data2));

        /**
         * 更新数据
         * */
        Stat stat = client.setData().forPath("/Korea");
        client.setData().withVersion(4).forPath("/Korea", "jinsanpangzi".getBytes());

        /**
         * 删除节点
         * */
        //只能删除叶子节点
        client.delete().forPath("/China");
        //删除一个节点,并递归删除其所有子节点
        client.delete().deletingChildrenIfNeeded().forPath("/aa");
        //强制指定版本进行删除
        client.delete().withVersion(4).forPath("/Korea");
        //注意:由于一些网络原因,上述的删除操作有可能失败,使用guaranteed(),
        // 如果删除失败,会记录下来,只要会话有效,就会不断的重试,直到删除成功为止
        client.delete().guaranteed().forPath("/America");
        
        
        Thread.sleep(Integer.MAX_VALUE);


    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值