Zookeeper基础
一、Zookeeper概述
什么是ZooKeeper
ZooKeeper是一个分布式开源框架,提供了协调分布式应用的基本服务,它向外部应用暴露一组通用服务——分布式同步(Distributed Synchronization)、命名服务(Naming Service)、集群维护(Group Maintenance)等,简化分布式应用协调及其管理的难度,提供高性能的分布式服务。ZooKeeper本身可以以Standalone模式安装运行,不过它的长处在于通过分布式ZooKeeper集群(一个Leader,多个Follower),基于一定的策略来保证ZooKeeper集群的稳定性和可用性,从而实现分布式应用的可靠性。并为用户程序提供数据节点监听服务;
二、Zookeeper结构
三、Windows环境下搭建Zookeeper
解压zookeeper-3.4.10.tar.gz ,重命名配置文件zoo_sample.cfg 为 zoo.cfgZookeeper实战分布式锁
一、使用Zookeeper实现分布式锁概述
二、解决生产订单号线程安全问题
三、实现分布式锁解决方案
四、Zookeeper概述
五、使用Zookeeper实现分布式锁
/** * lock锁 自定义分布式锁 * Created by yz on 2018/4/7. */ public interface Lock { // 获取锁 public void getLock(); // 释放锁 public void unLock(); }
import org.I0Itec.zkclient.ZkClient; import java.util.concurrent.CountDownLatch; /** * 重构重复代码,将重复代码交给子类执行 * Created by yz on 2018/4/7. */ public abstract class ZookeeperAbstractLock implements Lock{ // zk连接地址 private static final String CONNECTSTRING="127.0.0.1:2181"; // 创建zk连接 protected ZkClient zkClient = new ZkClient(CONNECTSTRING); protected static final String PATH="/lock"; protected CountDownLatch countDownLatch = null; @Override public void getLock() { if(tryLock()){ System.out.println("-----获取锁成功-----"); }else{ // 等待 waitLock(); // 信号量通知,重新获取锁 getLock(); } } // 等待 abstract void waitLock(); // 是否获取锁成功,成功返回true,失败返回false abstract Boolean tryLock(); @Override public void unLock() { if(zkClient !=null){ zkClient.close(); System.out.println("释放锁资源成功"); } } }
import org.I0Itec.zkclient.IZkDataListener; import java.util.concurrent.CountDownLatch; /** * Created by yz on 2018/4/7. */ public class ZookeeperDistrbuteLock extends ZookeeperAbstractLock{ @Override void waitLock() { // 使用zk事件监听,获取到节点被删除 IZkDataListener iZkDataListener = new IZkDataListener() { // 当节点发生改变执行 @Override public void handleDataChange(String s, Object o) throws Exception { } // 当节点被删除后执行 @Override public void handleDataDeleted(String s) throws Exception { if(countDownLatch !=null){ // 唤醒await countDownLatch.countDown(); } } }; //注册节点信息 zkClient.subscribeDataChanges(PATH,iZkDataListener); // 检测节点 if(zkClient.exists(PATH)){ // 创建信号量 countDownLatch = new CountDownLatch(1); try { // 等待 countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } // 删除事件通知 zkClient.unsubscribeDataChanges(PATH,iZkDataListener); } /** * 是否获取锁成功,成功返回true,失败返回false */ @Override Boolean tryLock() { try { zkClient.createEphemeral(PATH); return true; } catch (RuntimeException e) { return false; } } }
import java.text.SimpleDateFormat; import java.util.Date; /** * 生成订单号规则 使用时间戳+业务id * Created by yz on 2018/4/7. */ public class OrderNumGenerator { // 业务ID private static int count = 0; //生成订单号 public String getNumber(){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); return simpleDateFormat.format(new Date())+"_"+ ++count; } }
/** * 订单生成调用业务逻辑 * Created by yz on 2018/4/7. */ public class OrderService implements Runnable{ // 生成订单号 OrderNumGenerator orderNumGenerator = new OrderNumGenerator(); // 使用zk分布式锁 private Lock lock = new ZookeeperDistrbuteLock(); @Override public void run() { try { //上锁 lock.getLock(); getNumber(); } catch (Exception e) { e.printStackTrace(); }finally { // 是否锁资源 lock.unLock(); } } public void getNumber(){ String number = orderNumGenerator.getNumber(); System.out.println(Thread.currentThread().getName()+",##number:"+number); } public static void main(String[] args) { System.out.println("#模拟生成订单号..."); for (int i = 0; i < 100; i++) { new Thread(new OrderService()).start(); } } }