ZooKeeper 实现命名服务(分布式的ID生成器)
1、生成器类package com.zk.zkclient.nameservice;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import org.I0Itec.zkclien
1、生成器类
package com.zk.zkclient.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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Zookeeper的命名服务(ID生成器)
*
* @version 2016年11月29日上午9:51:37
* @author wuliu
*/
public class IdMaker {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private ZkClient client = null;
// 服务地址
private final String server;
// id生成器根节点
private final String root;
// id节点
private final String nodeName;
// 启动状态: true:启动;false:没有启动,默认没有启动
private volatile boolean running = false;
private ExecutorService cleanExector = null;
public enum RemoveMethod {
// 不,立即,延期
NONE, IMMEDIATELY, DELAY
}
public IdMaker(String zkServer, String root, String nodeName) {
this.server = zkServer;
this.root = root;
this.nodeName = nodeName;
}
/**
* 启动
*
* @version 2016年11月29日上午9:37:36
* @author wuliu
* @throws Exception
*/
public void start() throws Exception {
if (running)
throw new Exception("server has stated...");
running = true;
init();
}
/**
* 停止服务
*
* @version 2016年11月29日上午9:45:38
* @author wuliu
* @throws Exception
*/
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) {
logger.info("节点已经存在,节点路径:" + root);
}
}
/**
* 资源释放 T
*
* @version 2016年11月29日上午9:38:59
* @author wuliu
*/
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;
}
}
/**
* 判断是否启动服务
*
* @version 2016年11月29日上午9:39:58
* @author wuliu
* @throws Exception
*/
private void checkRunning() throws Exception {
if (!running)
throw new Exception("请先调用start启动服务");
}
/**
* 提取ID
*
* @version 2016年11月29日上午9:46:48
* @author wuliu
* @param str
* @return
*/
private String ExtractId(String str) {
int index = str.lastIndexOf(nodeName);// 20
if (index >= 0) {
index += nodeName.length();
return index <= str.length() ? str.substring(index) : "";
}
return str;
}
/**
* 获取id
*
* @version 2016年11月29日上午9:40:33
* @author wuliu
* @param removeMethod
* @return
* @throws Exception
*/
public String generateId(RemoveMethod removeMethod) throws Exception {
checkRunning();
final String fullNodePath = root.concat("/").concat(nodeName);
// 创建顺序节点每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。
// 基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,
// ZooKeeper会自动为给定节点名加上一个数字后缀,作为新的节点名
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);
}
}
2、测试
package com.zk.zkclient.nameservice;
import com.zk.zkclient.nameservice.IdMaker.RemoveMethod;
public class TestIdMaker {
public static void main(String[] args) throws Exception {
IdMaker idMaker = new IdMaker("127.0.0.1:2181",
"/NameService/IdGen", "ID-");
idMaker.start();
try {
for (int i = 0; i < 2; i++) {
String id = idMaker.generateId(RemoveMethod.DELAY);
System.out.println(id);
}
} finally {
idMaker.stop();
}
}
}
3、介绍
3.1、命名服务(提供名字的服务)
zookeeper的命名服务,有两个应用方向:
1、提供类似JNDI的功能:利用zookeeper中的树形分层结构,可以把系统中的各种服务的名称,地址以及目录信息存放在zookeeper中,
需要的时候去zookeeper中读取
2、利用zookeeper中的顺序节点的特性,制作分布式的序列号生成器(ID生成器),(在往数据库查询数据时,通常需要一个id,在单机环境下,可以利用数据库的自动成功id号,但是这种在分布式环境下就无法使用了,可以使用UUID,但是UUID有一个缺点,就是没有规律很难理解。使用zookeeper的命名服务可以生成有顺序的容易理解的,支持分布式的编号)
架构图:
算法流程图:
更多推荐
所有评论(0)