Zookeeper系列(三十三)Zookeeper场景应用之分布式ID生成器
来源:互联网 发布:mac怎么看硬盘文件 编辑:程序博客网 时间:2024/06/05 09:00
可以理解成一个分布式的ID生成器
1.命名服务
命名服务可以理解为提供名字的服务
Zookeeper的命名服务,有两个应用方向:
1.提供类似JNDI的功能:
利用zookeeper中的树形分层结构,可以把系统中的各种服务的名称,地址以及目录信息存放在zookeeper中,需要的时候去zookeeper中去读取
2.
利用zookeeper中的顺序节点的特性,制作分布式的序列号生成器(ID生成器)
(在往数据库中插入数据,通常是要有一个ID号,在单机环境下,可以利用数据库的主键自动生成id号,但是这种在分布式环境下就无法使用了,可以使用UUID,但是UUID有一个缺点,就是没有什么规律很难理解。使用zookeeper的命名服务可以生成有顺序的容易理解的,支持分布式的编号)
2.架构图
3.算法流程
生成ID的方法
- package com.jike.nameservice;
-
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.TimeUnit;
-
- import org.I0Itec.zkclient.ZkClient;
- import org.I0Itec.zkclient.exception.ZkNodeExistsException;
- import org.I0Itec.zkclient.serialize.BytesPushThroughSerializer;
-
- public class IdMaker {
-
-
- private ZkClient client = null;
- private final String server;
- 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){
-
- }
-
- }
-
-
-
-
- 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");
-
- }
-
- 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;
-
- }
-
-
-
-
-
-
-
-
- public String generateId(RemoveMethod removeMethod) throws Exception{
- checkRunning();
- final String fullNodePath = root.concat("/").concat(nodeName);
-
- final String ourPath = client.createPersistentSequential(fullNodePath, null);
-
-
-
-
-
- if (removeMethod.equals(RemoveMethod.IMMEDIATELY)){
- client.delete(ourPath);
- }else if (removeMethod.equals(RemoveMethod.DELAY)){
- cleanExector.execute(new Runnable() {
-
- public void run() {
-
- client.delete(ourPath);
- }
- });
-
- }
-
- return ExtractId(ourPath);
- }
-
- }
测试节点ID生成
- package com.jike.nameservice;
-
- import com.jike.nameservice.IdMaker.RemoveMethod;
-
- 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();
-
- }
- }
-
- }
0 0