zookeeper的分布式唯一id生成器

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

maven 依赖

<dependency>
    <groupId>org.apache.zookeeper</groupId>
	<artifactId>zookeeper</artifactId>
	<version>3.4.12</version>
</dependency>
<dependency>
	<groupId>org.apache.curator</groupId>
	<artifactId>curator-framework</artifactId>
	<version>2.8.0</version>
</dependency>
<dependency>
	<groupId>org.apache.curator</groupId>
	<artifactId>curator-recipes</artifactId>
	<version>2.8.0</version>
</dependency>

实现类:

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生成器
 * <p>
 * 创建人:ternence
 */
@Component
public class DistributedIdGeneraterService {
 
    private static CuratorFramework curatorFrameworkClient;
 
    private static RetryPolicy retryPolicy;
 
    private static ExecutorService executorService;
 
    private static String IP_TOSTRING = "47.74.214.10:2181,47.74.214.10:2182,47.74.214.10:2183";
 
    private static String ROOT = "/root";
 
    private static String NODE_NAME = "idgenerator";
 
    static {
    	// 0 000 000 004
        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  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 = 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;
    }
}

test:

private @Autowired DistributedIdGeneraterService bean;
System.out.println(bean.splitID(bean.generateId()));

输出结果:
生成的ID=0000000006
0000000006

注意:报错的解决方案
C:\Windows\System32\drivers\etc\hosts 里加入 ip

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值