一、简介

Zookeeper是一个分布式开源框架,提供了协调分布式应用的基本服务,它向外部应用暴露一组通用服务——分布式同步(Distributed Synchronization)、命名服务(Naming Service)、集群维护(Group Maintenance)等,简化分布式应用协调及其管理的难度,提供高性能的分布式服务

1、zk原理

1、数据结构类似于xml的树状结构

2、每个节点称为znode,包含节点名称(唯一),节点数据,子节点

2、znode类型

  临时节点:连接关闭后失效

  临时顺序节点:

  持久节点:节点信息持久化

  持久顺序节点:

二、zk环境搭建

1、windows环境

1、启动

  问题:点击zkServer.cmd后一闪而过

  原因:conf目录下不存在zoo.cfg文件,将实例文件改名

     3.5.5版本启动一闪而过问题,除了上述那个,需下载带bin的tar包,否则只是源码

 

 2、客户端连接

  点击zkCli.cmd

3、客户端常用命令

  ls /:查看根节点信息

  create /mytest znode_content:创建mytest节点,节点内容为znode_content ,默认创建的是持久节点

  set /mytest test_content_other:修改mytest节点内容

 2、java操作zk

1、事件状态对应事件类型

 

 2、创建持久节点

 

 3、zk事件通知watcher

// 增加持久节点
public boolean createPersistentNode(String path, String data) {
try {
  //新增订阅该节点的事件通知,也可查看该节点是否存在。针对该zk连接订阅通知
  zk.exists(path, true);
  String result = zk.create(path, data.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
  System.out.println("create node: " + result);
  return true;
} catch (KeeperException | InterruptedException e) {
  e.printStackTrace();
  return false;
}

}

@Override
public void process(WatchedEvent event) {
  KeeperState state = event.getState();
  if (state == KeeperState.SyncConnected) {
    EventType type = event.getType();
    if (type == EventType.None) {
      count.countDown();
      System.out.println("zk 连接成功");
    } else if (type == EventType.NodeCreated) {
      System.out.println("事件通知,创建节点:" + event.getPath());
    } else if (type == EventType.NodeDataChanged) {
      System.out.println("事件通知,节点数据修改:" + event.getPath());
    }
  }

}

三、zk实现分布式锁

1、分布式锁解决方案

1、数据库实现分布式锁,问题:连接断开无法解锁

2、使用缓存,问题:连接断开无法马上解锁

3、使用zk实现分布式锁

2、zk分布式锁原理

使用临时节点 + 事件通知

import java.util.concurrent.CountDownLatch;

import org.I0Itec.zkclient.ZkClient;

public abstract class ZKAbstractLock implements Lock {

public static final String ADDRESS = "127.0.0.1:2181";
protected ZkClient zkClient = new ZkClient(ADDRESS);
public static final String LOCK_PATH = "/lock";
protected CountDownLatch countDownLatch = null;

@Override
public void getLock() {
if (tryLock()) {
System.out.println("===获取锁成功===");
} else {
waitLock();
getLock();
}

}

public abstract boolean tryLock();

public abstract void waitLock();

@Override
public void unLock() {
if (zkClient != null) {
zkClient.close();
System.out.println("===释放锁成功===");
}

}

}

=====================================================

import java.util.concurrent.CountDownLatch;

import org.I0Itec.zkclient.IZkDataListener;

public class ZKDistributeLock extends ZKAbstractLock {

@Override
public boolean tryLock() {
try {
zkClient.createEphemeral(LOCK_PATH);
return true;
} catch (Exception e) {
return false;
}
}

@Override
public void waitLock() {
//定义监听事件操作
IZkDataListener iZkDataListener = new IZkDataListener() {

@Override
public void handleDataDeleted(String dataPath) throws Exception {
countDownLatch.countDown();

}

@Override
public void handleDataChange(String dataPath, Object data) throws Exception {
// TODO Auto-generated method stub

}
};
//该连接注册监听
zkClient.subscribeDataChanges(LOCK_PATH, iZkDataListener);
if (zkClient.exists(LOCK_PATH)) {
countDownLatch = new CountDownLatch(1);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
zkClient.unsubscribeDataChanges(LOCK_PATH, iZkDataListener);
}

}

=========================================================测试

mport test002_lock.OrderNumGenerator;
import test003.Lock;
import test003.ZKDistributeLock;

public class OrderService implements Runnable {

OrderNumGenerator orderNumGenerator = new OrderNumGenerator();
private Lock lock = new ZKDistributeLock();

@Override
public void run() {
try {
lock.getLock();
getNumber();
} catch (Exception e) {

} finally {
lock.unLock();
}

}

public String getNumber() {
String num = orderNumGenerator.genNum();
System.out.println(Thread.currentThread().getName() + " 获取订单号:" + num);
return num;
}

public static void main(String[] args) {
// OrderService orderService = new OrderService();
for (int i = 0; i < 100; i++) {
new Thread(new OrderService()).start();
}
}
}

4、zk实现负载均衡

 通过某节点下的所有临时子节点,获得集群信息,轮询算法进行负载均衡。

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2019-11-23 11:42  dysdhd  阅读(59)  评论(0)    收藏  举报