Curator链接zookeeper实现分布式锁

curator的特性,不必多说,可以说是 curator是zookeeper中的类似于guava对于java的意义一样,提供了丰富的封装,异常处理,提供了fluent编程模型,提供了master选举,分布式锁,分布式基数,分布式barrier,可以很方便的为日常生产所使用。

 这次主要用了curator的InterProcessMutex这种互斥锁来做,也借于此机会,阅读了它的代码,分享一下它的机制,共大家一起来交流学习下。

第一步:首先需要在pom中引入依赖的jar:

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.9</version>
        </dependency>
        <!--curator-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.12.0</version>
        </dependency>

第二步:创建一个zookeeper链接的维护类:

@Setter
@Getter
public class TestingServer implements Closeable {
    private String connectString;

    public TestingServer(){
        this.connectString = "10.7.28.179:2181,10.7.28.180:2181,10.7.28.181:2181";
    }

    @Override
    public void close() throws IOException {
        System.out.println("关闭连接");
    }
}

第三步:共享资源处理类,每次只期望单线程访问,否则会有并发问题

public class FakeLimitedResource {
    private final AtomicBoolean inUse = new AtomicBoolean(false);
    public void use() throws InterruptedException {
        // 真实环境中我们会在这里访问/维护一个共享的资源
        //这个例子在使用锁的情况下不会非法并发异常IllegalStateException
        //但是在无锁的情况由于sleep了一段时间,很容易抛出异常
        if (!inUse.compareAndSet(false, true)) {
            throw new IllegalStateException("Needs to be used by one client at a time");
        }
        try {
            Thread.sleep((long) (3 * Math.random()));
        } finally {
            inUse.set(false);
        }
    }
}
第四步:封装了zookeeper锁的工具类
/**
 * Created by Administrator on 2017/9/8.
 * 封装了zookeeper锁的工具类
 */
public class ExampleClientThatLocks {
    private final InterProcessMutex lock;
    //封装定义了资源的处理类
    private final FakeLimitedResource resource;
    private final String clientName;

    public ExampleClientThatLocks(CuratorFramework client, String lockPath, FakeLimitedResource resource, String clientName) {
        this.resource = resource;
        this.clientName = clientName;
        lock = new InterProcessMutex(client, lockPath);
    }

    /**
     * 线程进来获取锁,释放锁的方法
     * @param time
     * @param unit
     * @throws Exception
     */
    public void doWork(long time, TimeUnit unit) throws Exception {
        //线程阻塞等待锁的超时时间为time,如果时间超过时间限制则lock.acquire()返回false,抛出等待锁失败的异常
        if (!lock.acquire(time, unit)) {
            throw new IllegalStateException(clientName + " could not acquire the lock");
        }
        try {
            System.out.println(clientName + " has the lock");
            resource.use(); //access resource exclusively
        } finally {
            System.out.println(clientName + " releasing the lock");
            lock.release(); // always release the lock in a finally block
        }
    }
}

第五步:创建测试类同时启动100个线程去竞争锁:

/**
 * Created by Administrator on 2017/9/8.
 * 重入锁测试类
 */
public class InterProcessMutexExample {
    //同时启动100个线程去竞争共享资源
    private static final int QTY = 100;
    private static final String PATH = "/examples/locks";
    public static void main(String[] args) throws Exception {
        FakeLimitedResource resource = new FakeLimitedResource();
        ExecutorService service = Executors.newFixedThreadPool(QTY);
        final TestingServer server = new TestingServer();
        try {
            for (int i = 0; i < QTY; ++i) {
                final int index = i;
                Callable<Void> task = new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new ExponentialBackoffRetry(1000, 3));
                        try {
                            client.start();
                            final ExampleClientThatLocks example = new ExampleClientThatLocks(client, PATH, resource, "Client " + index);
                            example.doWork(1, TimeUnit.SECONDS);
                        } catch (Throwable e) {
                            e.printStackTrace();
                        } finally {
                            CloseableUtils.closeQuietly(client);
                        }
                        return null;
                    }
                };
                service.submit(task);
            }
            service.shutdown();
            service.awaitTermination(10, TimeUnit.MINUTES);
        } finally {
            CloseableUtils.closeQuietly(server);
        }
    }
}
贴出部分执行结果如下所示:

Client 10 has the lock
Client 10 releasing the lock
Client 38 has the lock
Client 38 releasing the lock
Client 97 has the lock
Client 97 releasing the lock
Client 76 has the lock
Client 76 releasing the lock
Client 50 has the lock
Client 50 releasing the lock
Client 34 has the lock
Client 34 releasing the lock
Client 33 has the lock
Client 33 releasing the lock
Client 2 has the lock
Client 2 releasing the lock
Client 78 has the lock
Client 78 releasing the lock
Client 18 has the lock
Client 18 releasing the lock
Client 49 has the lock
Client 49 releasing the lock
Client 82 has the lock
Client 82 releasing the lock
Client 77 has the lock
Client 77 releasing the lock
Client 51 has the lock
Client 51 releasing the lock



参考资料:http://www.jianshu.com/p/70151fc0ef5d

Curator深入使用:http://www.cnblogs.com/LiZhiW/p/4926385.html



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值