zookeeper应用场景练习(分布式锁)
来源:互联网 发布:协同过滤推荐算法实例 编辑:程序博客网 时间:2024/06/04 18:56
在平常的高并发的程序中,为了保证数据的一致性,因此都会用到锁,来对当前的线程进行锁定。在单机操作中,很好做到,比如可以采用Synchronized、Lock或者其他的读写多来锁定当前的线程。但是在分布式的系统中,就很难做到这一点。因此可以采用zookeeper中节点的特性来满足这一点。大致实现的思路如下。
1.每个客户端都去zookeeper上创建临时的顺序节点
2.客户端判断当前自己创建的节点是不是最小的
3.如果是的话,就获得了执行当前任务的锁
4.如果不是的话,就找到比自己小的节点,然后进行监听,如果被删除的话,就可以获得锁
上面就是大致的实现思路,下面我们来通过代码来实现一下。
package com.test;import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.concurrent.CountDownLatch;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.CuratorFrameworkFactory;import org.apache.curator.framework.api.CuratorWatcher;import org.apache.curator.framework.state.ConnectionState;import org.apache.curator.framework.state.ConnectionStateListener;import org.apache.curator.retry.RetryNTimes;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher.Event.EventType;import org.apache.zookeeper.data.Stat;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class DistributedLock {private String lockName;private final int timeOut = 3000;private final String root = "/locks";private String myZnode;// 代表当前节点信息private String waitZnode;private static Logger logger = LoggerFactory.getLogger(DistributedLock.class);private CuratorFramework client;private CountDownLatch latch = new CountDownLatch(1);public DistributedLock(String connectString, String lockName) {this.lockName = lockName;client = CuratorFrameworkFactory.builder().connectionTimeoutMs(timeOut).connectString(connectString).retryPolicy(new RetryNTimes(3, 3000)).build();ConnectionStateListener listener = new ConnectionStateListener() {public void stateChanged(CuratorFramework client,ConnectionState newState) {if (newState == ConnectionState.CONNECTED) {logger.info("连接成功了");latch.countDown();}}};client.getConnectionStateListenable().addListener(listener);client.start();try {latch.await();createRoot();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/** * @Title: 创建根节点root * @Description: TODO * @param * @return void * @throws */private void createRoot() {try {Stat stat = client.checkExists().forPath(root);if (stat != null) {logger.info("root has already exists");} else {// 创建跟节点client.create().creatingParentsIfNeeded().forPath(root);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void getLocks() {try {myZnode = client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(root + "/" + lockName);logger.info(myZnode + "has created");// 取出所有的子节点,然后找出比自己小的节点,进行监听的设置List<String> subNodes = client.getChildren().forPath(root);// 取出所有带有lockname的节点信息List<String> lockObjNodes = new ArrayList<String>();for (String node : subNodes) {if (node.contains(lockName)) {lockObjNodes.add(node);}}// 对当前节点进行排序Collections.sort(lockObjNodes);// 判断当前的节点是不是最小的节点if (myZnode.equals(root + "/" + lockObjNodes.get(0))) {doAction();} else {// 找到比自己节点大一的节点进行监听String subMyZone = myZnode.substring(myZnode.lastIndexOf("/") + 1);waitZnode = lockObjNodes.get(Collections.binarySearch(lockObjNodes, subMyZone) - 1);// 对节点进行监听Stat stat = client.checkExists().usingWatcher(deleteNodeWatcher).forPath("/"+waitZnode);if (stat != null) {System.out.println(Thread.currentThread().getName()+ "处于等待状态");} else {doAction();}}} catch (Exception e) {logger.error(e.getMessage());}}// 删除节点的事件监听CuratorWatcher deleteNodeWatcher = new CuratorWatcher() {public void process(WatchedEvent event) throws Exception {if (event.getType() == EventType.NodeDeleted) {doAction();}}};private void doAction() {System.out.println(Thread.currentThread().getName() + "开始执行");client.close();}}
下面来测试一下
/** * @FileName: TestCurrentZk.java * @Package:com.test * @Description: TODO * @author: LUCKY * @date:2016年2月2日 下午11:36:04 * @version V1.0 */package com.test;/** * @ClassName: TestCurrentZk * @Description: TODO * @author: LUCKY * @date:2016年2月2日 下午11:36:04 */public class TestCurrentZk {public static void main(String[] args) throws Exception {Thread threads[] = new Thread[10];for (int i = 0; i < threads.length; i++) {threads[i] = new Thread(new Runnable() {public void run() {ClientTest clientTest = new ClientTest("100.66.162.36:2181", "locknametest");clientTest.getLocks();}});threads[i].start();}Thread.sleep(Integer.MAX_VALUE);}}
1 0
- zookeeper应用场景练习(分布式锁)
- 【分布式】Zookeeper应用场景
- 【分布式】Zookeeper应用场景
- ZooKeeper应用场景-分布式锁设计
- ZooKeeper应用场景-分布式锁实现范例
- Zookeeper系列(三十二)Zookeeper场景应用之分布式队列
- Zookeeper系列(二十九)Zookeeper场景应用之分布式锁实现
- ZooKeeper场景实践:(7) 分布式锁
- ZooKeeper的典型应用场景之分布式锁。
- zookeeper应用场景练习(数据发布/订阅)
- Zookeeper系列(三十一)Zookeeper场景应用之配置服务和分布式锁实列
- Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器
- zookeeper(三) 应用场景
- zookeeper适用场景:分布式锁实现
- Zookeeper场景实践:(8) 分布式队列
- 分布式服务协调员zookeeper - 应用场景和监控
- ZooKeeper的典型应用场景之分布式协调/通知。
- ZooKeeper的典型应用场景之分布式队列。
- Linux:C/Socket多路复用select
- NSURLSession使用说明及后台工作流程分析
- EventBus猜想 ----手把手带你自己实现一个EventBus
- android 65535 多dex文件方案
- spring mvc+ mybaties+ehcache(maven工程),在mapper.xml中使用
- zookeeper应用场景练习(分布式锁)
- CLLocationCoordinate2D 初始化
- Angular的作用域Scope理解
- Redis 实例: 集群
- php中必须表单
- spring mvc+ mybaties+ehcache(maven工程),在service层中使用
- unity5中AssetBundle相关
- ViewPager实现一个页面多个Item的显示
- swift-UI-01