zookeeper系列(一)zookeeper必知
zookeeper系列(二)实战master选举
zookeeper系列(三)实战数据发布订阅
zookeeper系列(四)实战负载均衡
zookeeper系列(五)实战分布式锁
zookeeper系列(六)实战分布式队列
zookeeper系列(七)实战分布式命名服务
zookeeper系列(八)zookeeper运维java
zookeeper的命名服务有两个应用方向,一个是提供相似JNDI的功能,利用zookeepeer的树型分层结构,能够把系统中各类服务的名称、地址以及目录信息存放在zookeeper,须要的时候去zookeeper中读取。node
另外一个,是利用zookeeper顺序节点的特性,制做分布式的ID生成器,写过数据库应用的朋友都知道,咱们在往数据库表中插入记录时,一般须要为该记录建立惟一的ID,在单机环境中咱们能够利用数据库的主键自增功能。但在分布式环境则没法使用,有一种方式能够使用UUID,可是它的缺陷是没有规律,很难理解。利用zookeeper顺序节点的特性,咱们能够生成有顺序的,容易理解的,同时支持分布式环境的序列号。数据库
public class IdMaker { private ZkClient client = null; private final String server; // zookeeper顺序节点的父节点 private final String root; // 顺序节点的名称 private final String nodeName; // 标识当前服务是否正在运行 private volatile boolean running = false; private ExecutorService cleanExector = null; public enum RemoveMethod{ NONE,IMMEDIATELY,DELAY } public IdMaker(String zkServer,String root,String nodeName){ this.root = root; this.server = zkServer; this.nodeName = nodeName; } // 启动服务 public void start() throws Exception { if (running) throw new Exception("server has stated..."); running = true; init(); } // 中止服务 public void stop() throws Exception { if (!running) throw new Exception("server has stopped..."); running = false; freeResource(); } // 初始化服务资源 private void init(){ client = new ZkClient(server,5000,5000,new BytesPushThroughSerializer()); cleanExector = Executors.newFixedThreadPool(10); try{ client.createPersistent(root,true); }catch (ZkNodeExistsException e){ //ignore; } } // 释放服务器资源 private void freeResource(){ // 释放线程池 cleanExector.shutdown(); try{ cleanExector.awaitTermination(2, TimeUnit.SECONDS); }catch(InterruptedException e){ e.printStackTrace(); }finally{ cleanExector = null; } if (client!=null){ client.close(); client=null; } } // 检测当前服务是否正在运行 private void checkRunning() throws Exception { if (!running) throw new Exception("请先调用start"); } // 从顺序节点名中提取咱们要的ID值 private String ExtractId(String str){ int index = str.lastIndexOf(nodeName); if (index >= 0){ index+=nodeName.length(); return index <= str.length()?str.substring(index):""; } return str; } // 生成ID public String generateId(RemoveMethod removeMethod) throws Exception{ checkRunning(); // 构造顺序节点的完整路径 final String fullNodePath = root.concat("/").concat(nodeName); // 建立持久化顺序节点 final String ourPath = client.createPersistentSequential(fullNodePath, null); // 避免zookeeper的顺序节点暴增,直接删除掉刚建立的顺序节点 if (removeMethod.equals(RemoveMethod.IMMEDIATELY)){ // 当即删除 client.delete(ourPath); }else if (removeMethod.equals(RemoveMethod.DELAY)){ // 延迟删除 cleanExector.execute(new Runnable() { // 用线程池执行删除,让generateId()方法尽快返回 public void run() { client.delete(ourPath); } }); } //node-0000000000, node-0000000001 return ExtractId(ourPath); } }
public class TestIdMaker { public static void main(String[] args) throws Exception { IdMaker idMaker = new IdMaker("192.168.1.105:2181", "/NameService/IdGen", "ID"); idMaker.start(); try { for (int i = 0; i < 10; i++) { String id = idMaker.generateId(RemoveMethod.DELAY); System.out.println(id); } } finally { idMaker.stop(); } } }
zookeeper系列(一)zookeeper必知
zookeeper系列(二)实战master选举
zookeeper系列(三)实战数据发布订阅
zookeeper系列(四)实战负载均衡
zookeeper系列(五)实战分布式锁
zookeeper系列(六)实战分布式队列
zookeeper系列(七)实战分布式命名服务
zookeeper系列(八)zookeeper运维segmentfault