Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器

可以理解成一个分布式的ID生成器

1.命名服务

命名服务可以理解为提供名字的服务

Zookeeper的命名服务,有两个应用方向:

   1.提供类似JNDI的功能:

             利用zookeeper中的树形分层结构,可以把系统中的各种服务的名称,地址以及目录信息存放在zookeeper中,需要的时候去zookeeper中去读取

   2.

            利用zookeeper中的顺序节点的特性,制作分布式的***生成器(ID生成器)

(在往数据库中插入数据,通常是要有一个ID号,在单机环境下,可以利用数据库的主键自动生成id号,但是这种在分布式环境下就无法使用了,可以使用UUID,但是UUID有一个缺点,就是没有什么规律很难理解。使用zookeeper的命名服务可以生成有顺序的容易理解的,支持分布式的编号)

2.架构

Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器

3.算法流程

Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器


生成ID的方法

[java] view plain copy
 Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器
  1. package com.jike.nameservice;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5. import java.util.concurrent.TimeUnit;  
  6.   
  7. import org.I0Itec.zkclient.ZkClient;  
  8. import org.I0Itec.zkclient.exception.ZkNodeExistsException;  
  9. import org.I0Itec.zkclient.serialize.BytesPushThroughSerializer;  
  10.   
  11. public class IdMaker {  
  12.       
  13.       
  14.     private ZkClient client = null;  
  15.     private final String server;//记录服务器的地址  
  16.     private final String root;//记录父节点的路径  
  17.     private final String nodeName;//节点的名称  
  18.     private volatile boolean running = false;  
  19.     private ExecutorService cleanExector = null;  
  20.       
  21.     //删除节点的级别  
  22.     public enum RemoveMethod{  
  23.         NONE,IMMEDIATELY,DELAY  
  24.           
  25.     }  
  26.       
  27.     public IdMaker(String zkServer,String root,String nodeName){  
  28.           
  29.         this.root = root;  
  30.         this.server = zkServer;  
  31.         this.nodeName = nodeName;  
  32.           
  33.     }  
  34.       
  35.     public void start() throws Exception {  
  36.           
  37.         if (running)  
  38.             throw new Exception("server has stated...");  
  39.         running = true;  
  40.           
  41.         init();  
  42.           
  43.     }  
  44.       
  45.       
  46.     public void stop() throws Exception {  
  47.           
  48.         if (!running)  
  49.             throw new Exception("server has stopped...");  
  50.         running = false;  
  51.           
  52.         freeResource();  
  53.           
  54.     }  
  55.       
  56.     /** 
  57.      * 初始化服务资源 
  58.      */  
  59.     private void init(){  
  60.           
  61.         client = new ZkClient(server,5000,5000,new BytesPushThroughSerializer());  
  62.         cleanExector = Executors.newFixedThreadPool(10);  
  63.         try{  
  64.             client.createPersistent(root,true);  
  65.         }catch (ZkNodeExistsException e){  
  66.             //ignore;  
  67.         }  
  68.           
  69.     }  
  70.       
  71.     /** 
  72.      * 释放服务资源 
  73.      */  
  74.     private void freeResource(){  
  75.       
  76.         cleanExector.shutdown();  
  77.         try{  
  78.             cleanExector.awaitTermination(2, TimeUnit.SECONDS);  
  79.               
  80.         }catch(InterruptedException e){  
  81.             e.printStackTrace();  
  82.         }finally{  
  83.             cleanExector = null;  
  84.         }  
  85.       
  86.         if (client!=null){  
  87.             client.close();  
  88.             client=null;  
  89.               
  90.         }  
  91.     }  
  92.       
  93.     /** 
  94.      * 检测服务是否正在运行 
  95.      * @throws Exception 
  96.      */  
  97.     private void checkRunning() throws Exception {  
  98.         if (!running)  
  99.             throw new Exception("请先调用start");  
  100.           
  101.     }  
  102.       
  103.     private String ExtractId(String str){  
  104.         int index = str.lastIndexOf(nodeName);  
  105.         if (index >= 0){  
  106.             index+=nodeName.length();  
  107.             return index <= str.length()?str.substring(index):"";  
  108.         }  
  109.         return str;  
  110.           
  111.     }  
  112.       
  113.     /** 
  114.      * 产生ID 
  115.      * 核心函数 
  116.      * @param removeMethod 删除的方法 
  117.      * @return 
  118.      * @throws Exception 
  119.      */  
  120.     public String generateId(RemoveMethod removeMethod) throws Exception{  
  121.         checkRunning();  
  122.         final String fullNodePath = root.concat("/").concat(nodeName);  
  123.         //返回创建的节点的名称  
  124.         final String ourPath = client.createPersistentSequential(fullNodePath, null);  
  125.           
  126.           
  127.         /** 
  128.          * 在创建完节点后为了不 
  129.          */  
  130.         if (removeMethod.equals(RemoveMethod.IMMEDIATELY)){  
  131.             client.delete(ourPath);  
  132.         }else if (removeMethod.equals(RemoveMethod.DELAY)){  
  133.             cleanExector.execute(new Runnable() {  
  134.                   
  135.                 public void run() {  
  136.                     // TODO Auto-generated method stub  
  137.                     client.delete(ourPath);  
  138.                 }  
  139.             });  
  140.               
  141.         }  
  142.         //node-0000000000, node-0000000001,ExtractId提取ID  
  143.         return ExtractId(ourPath);  
  144.     }  
  145.   
  146. }  

测试节点ID生成

[java] view plain copy
 Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器
  1. package com.jike.nameservice;  
  2.   
  3. import com.jike.nameservice.IdMaker.RemoveMethod;  
  4.   
  5. public class TestIdMaker {  
  6.   
  7.     public static void main(String[] args) throws Exception {  
  8.           
  9.         IdMaker idMaker = new IdMaker("192.168.1.105:2181",  
  10.                 "/NameService/IdGen""ID");  
  11.         idMaker.start();  
  12.   
  13.         try {  
  14.             for (int i = 0; i < 10; i++) {  
  15.                 String id = idMaker.generateId(RemoveMethod.DELAY);  
  16.                 System.out.println(id);  
  17.   
  18.             }  
  19.         } finally {  
  20.             idMaker.stop();  
  21.   
  22.         }  
  23.     }  
  24.   
  25. }