基于zookeeper的分布式唯一id生成器

之前已简单介绍过Curator客户端的使用,并利用Curator实现了分布式锁和master选举,文章链接:https://blog.csdn.net/fanrenxiang/article/details/83013218   本文简述分库分表之后分布式下如何保证ID全局唯一性,可以用普通的UUID来实现,但是UUID是杂乱无规律的,相反,我们利用zookeeper的持久顺序节点特性,多个客户端同时创建同一节点,zk保证了能有序的创建,创建成功并返回的path类似于/root/generateid0000000001酱紫的,可以看到是顺序有规律的,能较好的解决这个问题,缺点是,会依赖于zk。


    org.apache.zookeeper
	zookeeper
	3.4.12


	org.apache.curator
	curator-framework
	2.8.0


	org.apache.curator
	curator-recipes
	2.8.0
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 类描述:分布式唯一ID生成器
 * 

* 创建人:simonsfan */ @Component public class DistributedIdGeneraterService { private static CuratorFramework curatorFrameworkClient; private static RetryPolicy retryPolicy; private static ExecutorService executorService; private static String IP_TOSTRING = "10.200.121.46:2181,10.200.121.43:2181,10.200.121.167:2181"; private static String ROOT = "/root"; private static String NODE_NAME = "idgenerator"; static { retryPolicy = new ExponentialBackoffRetry(1000, 3); curatorFrameworkClient = CuratorFrameworkFactory .builder() .connectString(IP_TOSTRING) .sessionTimeoutMs(5000) .connectionTimeoutMs(5000) .retryPolicy(retryPolicy) .build(); curatorFrameworkClient.start(); try { executorService = Executors.newFixedThreadPool(10); //请先判断父节点/root节点是否存在 Stat stat = curatorFrameworkClient.checkExists().forPath(ROOT); if (stat == null) { curatorFrameworkClient.create().withMode(CreateMode.PERSISTENT).forPath(ROOT, null); } } catch (Exception e) { e.printStackTrace(); } } public static String generateId() { String backPath = ""; String fullPath = ROOT.concat("/").concat(NODE_NAME); try { // 关键点:创建持久顺序节点 backPath = curatorFrameworkClient.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath(fullPath, null); //为防止生成的节点浪费系统资源,故生成后异步删除此节点 String finalBackPath = backPath; executorService.execute(() -> { try { curatorFrameworkClient.delete().forPath(finalBackPath); } catch (Exception e) { e.printStackTrace(); } }); String ID = this.splitID(backPath); System.out.println("生成的ID=" + ID); } catch (Exception e) { e.printStackTrace(); } return backPath; } public String splitID(String path) { int index = path.lastIndexOf(NODE_NAME); if (index >= 0) { index += NODE_NAME.length(); return index <= path.length() ? path.substring(index) : ""; } return path; } }


books 引申阅读: Zookeeper入门

books 引申阅读: Zookeeper客户端Curator使用指南

你可能感兴趣的:(Zookeeper,Zookeeper教程)