zookeeper+curator 分布式id

实现原理

zookeeper操作path数据时,version会增量+1,这个version可以当作分布式id使用。
注意:
1.path必须为持久节点

  • 本文基于springboot示例

具体实现

  • 引入依赖
    ps: Zookeeper原生API比较复杂度。Curator帮助我们在其基础上进行封装、实现一些开发细节、Fluent的编程风格。目前为Apache的顶级项目,是最流行的Zookeeper客户端之一。
        <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.6.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>5.0.0</version>
        </dependency>
  • zookeeper config
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryForever;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ZookeeperConfig {
    @Bean
    public CuratorFramework curatorFramework(){
        CuratorFramework cf = CuratorFrameworkFactory.builder()
                .connectString("192.168.0.xxx:2181,192.168.0.xxx:2182,192.168.0.xxx:2183")
                .sessionTimeoutMs(60000)
                .connectionTimeoutMs(2000)
                .retryPolicy(new RetryForever(2000))
                .namespace("test")
                .build();

        cf.start();
        return cf;
    }}
  • 具体实现类
import com.dang.util.SpringContextUtil;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.data.Stat;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

/**
 * zookeeper 获取递增id
 */
public class ZkIncrementId {

    CuratorFramework curatorFramework = SpringContextUtil.getBean(CuratorFramework.class);
    private final byte[] emptyValue = new byte[0];
    private String basePath = "/incrementId";
    private String extPath = null;
    private LocalDate date = null;

    private final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     *  构造函数
     * @param basePath 根目录
     */
    public  ZkIncrementId(String basePath){
        this.extPath = extPath;
        init();
    }

    /**
     *  构造函数
     * @param basePath 根目录
     * @param date 按日期生成
     */
    public  ZkIncrementId(String basePath,LocalDate date){
        this.extPath = basePath;
        this.date = date;
        init();
    }

    public int next(){
        String path = getPath();
        try {
            return curatorFramework.setData().forPath(path,emptyValue).getVersion();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private void init(){
        String path = getPath();
        try {
            if (curatorFramework.checkExists().forPath(path)==null){
                //Stat stat = new Stat();
                curatorFramework.create()
                        .creatingParentsIfNeeded()
                  //      .storingStatIn(stat)
                        .forPath(path,emptyValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private String getPath(){

        return basePath
                .concat(this.extPath==null?""
                        :extPath.indexOf("/")==0?extPath
                        :("/"+extPath))
                .concat(this.date==null?"":
                        ("/"+df.format(this.date)));
    }

}
  • spring获取bean辅助类
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextUtil  implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext contex) throws BeansException {
        System.out.println("--------------------SpringContextUtil--------------------");
        context = contex;
    }

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    public static <T> T getBean(Class<T> clazz) {
        return context.getBean(clazz);
    }

    public static <T> T getBean(String beanName) {
        return (T) context.getBean(beanName);
    }

    public static String getActiveProfile() {
        return context.getEnvironment().getActiveProfiles()[0];
    }
}

调用示例

        //path  defaultId 下自增长id
        ZkIncrementId zkIncrementId1 = new ZkIncrementId("defaultId");
        zkIncrementId1.next();
        //path orderid 下,按天,自增长id
        ZkIncrementId zkIncrementId2 = new ZkIncrementId("orderid",LocalDate.now());
        zkIncrementId2.next();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值