2

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>

原理

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

  • 节点的特性
    持久顺序节点(PERSISTENT_SEQUENTIAL)
    他的基本特性和持久节点是一致的,额外的特性表现在顺序性上。在ZooKeeper中,每个父节点都会为他的第一级子节点维护一份顺序,用于记录下每个子节点创建的先后顺序。基于这个顺序特性,在创建子节点的时候,可以设置这个标记,那么在创建节点过程中,ZooKeeper会自动为给定节点加上一个数字后缀,作为一个新的、完整的节点名。另外需要注意的是,这个数字后缀的上限是整型的最大值。
  • 版本-保证分布式数据原子性操作
    ZooKeeper中为数据节点引入了版本的概念,每个数据节点都具有三种类型的版本信息,对数据节点的任何更新操作都会引起版本号的变化。

代码实现

第一种根据节点方式:

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


import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
 
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
 
/**
* 类描述:Curator实现的分布式锁
* 创建人:simonsfan
*/
public class DistributedLock {
 
    private static CuratorFramework curatorFramework;
 
    private static InterProcessMutex interProcessMutex;
 
    private static final String connectString = "localhost:2181";
 
    private static final String root = "/root";
 
    private static ExecutorService executorService;
 
    private String lockName;
 
    public String getLockName() {
        return lockName;
    }
 
    public void setLockName(String lockName) {
        this.lockName = lockName;
    }
 
    static {
        curatorFramework = CuratorFrameworkFactory.builder().connectString(connectString).connectionTimeoutMs(5000).sessionTimeoutMs(5000).retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
        executorService = Executors.newCachedThreadPool();
        curatorFramework.start();
    }
 
    public DistributedLock(String lockName) {
        this.lockName = lockName;
        interProcessMutex = new InterProcessMutex(curatorFramework, root.concat(lockName));
    }
 
    /*上锁*/
    public boolean tryLock() {
        int count = 0;
        try {
            while (!interProcessMutex.acquire(100, TimeUnit.SECONDS)) {
                count++;
                if (count > 3) {
                    TimeUnit.SECONDS.sleep(1);
                    return false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
 
    /*释放*/
    public void releaseLock() {
        try {
            if (interProcessMutex != null) {
                interProcessMutex.release();
            }
            curatorFramework.delete().inBackground(new BackgroundCallback() {
                @Override
                public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
 
                }
            }, executorService).forPath(root.concat(lockName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 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");
//        System.out.println( zkIdGenerator.next());
//        for (int i = 0; i < 1000; i++) {
//        }

    }
 
}

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

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

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

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

    }
 
}

版本生成的:
在这里插入图片描述


Smile3k
197 声望22 粉丝