zookeeper生成全局唯一id

依赖

<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>
  <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>

原理

实现方式有两种,一种通过节点,一种通过节点的版本号

  • 节点的特性
    持久顺序节点(PERSISTENT_SEQUENTIAL)
    他的基本特性和持久节点是一致的,额外的特性表现在顺序性上。在ZooKeeper中,每个父节点都会为他的第一级子节点维护一份顺序,用于记录下每个子节点创建的先后顺序。基于这个顺序特性,在创建子节点的时候,可以设置这个标记,那么在创建节点过程中,ZooKeeper会自动为给定节点加上一个数字后缀,作为一个新的、完整的节点名。另外需要注意的是,这个数字后缀的上限是整型的最大值。

  • 版本-保证分布式数据原子性操作
    ZooKeeper中为数据节点引入了版本的概念,每个数据节点都具有三种类型的版本信息,对数据节点的任何更新操作都会引起版本号的变化。

代码实现

第一种根据节点方式:

创建持久顺序节点,只要不把节点删除,那么就不会重复;


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 java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 分布式唯一ID生成器
 */
public class DistributedIdGeneraterService {

    private static CuratorFramework curatorFrameworkClient;

    private static RetryPolicy retryPolicy;

    private static ExecutorService executorService;

    private static String IP_TOSTRING = "127.0.0.1:2181";

    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;
    }

    public static void main(String[] args) {

        for (int i = 0; i < 100; i++) {
            DistributedIdGeneraterService distributedIdGeneraterService = new DistributedIdGeneraterService();
            String s = distributedIdGeneraterService.generateId();
            System.out.println(s);
        }

    }

}

生成的节点:
在这里插入图片描述

第二种根据节点版本方式:

只要修改了节点,版本号就会加一.
代码:

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;

/**
 * 使用zk生成分布式唯一id,自增有序
 *
 * @author CC11001100
 */
public class ZkIdGenerator {
 
    private ZooKeeper zk;
    private String path;
 
    public ZkIdGenerator(String serverAddress, String path) {
        try {
            this.path = path;
            zk = new ZooKeeper(serverAddress, 3000, event -> {
                System.out.println(event.toString());
            });
 
            if (zk.exists(path, false) == null) {
                zk.create(path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
        } catch (IOException | InterruptedException | KeeperException e) {
            e.printStackTrace();
        }
    }
 
    public long next() {
        try {
            Stat stat = zk.setData(path, new byte[0], -1);
            return stat.getVersion();
        } catch (KeeperException | InterruptedException e) {
            e.printStackTrace();
        }
        return -1;
    }

public static void main(String[] args) {


//        for (int i = 0; i < 1000; i++) {
//            DistributedIdGeneraterService distributedIdGeneraterService = new DistributedIdGeneraterService();
//            String s = distributedIdGeneraterService.generateId();
//            System.out.println(s);
//        }


        ZkIdGenerator zkIdGenerator = new ZkIdGenerator("localhost:2181", "/id-gen");
     
        for (int i = 0; i < 1000; i++) {
           System.out.println(zkIdGenerator.next());
        }

    }
 
}

版本生成的:
在这里插入图片描述
根据自己的业务选择合适的即可…

好玩的

使用图形化工具https://blog.csdn.net/qq_38366063/article/details/93495348操作的时候
一直生成id,然后就:
*加粗样式
旁边一直出来,哈哈哈!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值