问题来源:

微服务的框架,有的服务部署了多个实例,同时需要全局的自增id,当然使用uuid作为id是可以不用关系id的生成,但是如果要是序列sequence就需要自己实现id的生成,但是分布式环境下如何保证不会重复生成相同的id?

解决办法

1, 使用分布式锁,每次生成sequence时先获取全局锁,然后获取sequence,接着sequence+1并保存到持久存储中,最后释放锁。
2,使用已有的框架提供分布式锁的,例如Redis,ZooKeeper。

本文选择使用zookeeper作为例子, 具体代码在这里,欢迎加星,fork

具体实现

我使用zk的官方client,zk还有非常好用的curator客户端。

因此pom文件需要添加如下依赖

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.9</version>
        </dependency>

具体示例代码如下,本代码非生产级别代码,只是作为示例。

package com.yq;


import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * Simple to Introduction
 * className: ZKDemoOneApplication
 *
 * @author EricYang
 * @version 2018/8/24 23:43
 */

public class ZKClientSequenceApp {
    private static ZooKeeper zk = null;
    private static final Logger log = LoggerFactory.getLogger(ZKClientSequenceApp.class);
    private static final String ZK_SERVERS = "127.0.0.1:2181";
    private static final int SESSION_TIME = 2000;
    private static final String PARENT_PATH_NAME_TEST = "/yqseq_test001";
    private static final String CHILD_PATH_NAME_TEST = "/yqseq_test001/";
    public static void main(String[] args) throws Exception {
        zk = new ZooKeeper(ZK_SERVERS,SESSION_TIME, null);
        Stat stat = zk.exists(PARENT_PATH_NAME_TEST, null);
        if (stat == null) {
            String zkParentPath = zk.create(PARENT_PATH_NAME_TEST, "helloWorld".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            log.info("zkParentPath={}", zkParentPath);
        }

        String zkPath = zk.create(CHILD_PATH_NAME_TEST, "helloWorld".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
        log.info("zkPath={}", zkPath);
        List<String> children = zk.getChildren(PARENT_PATH_NAME_TEST, null);

        for(String seq : children) {
            log.info("seq={}", seq);
        }

        log.info("start done.");
    }
}

关于zookeeper如何保证CreateMode.PERSISTENT_SEQUENTIAL path不会重复后面会加上解释。
程序每运行一次就或生成一个新的自增1的path, path就是sequece, 例如0000000001。 本文没有删除旧的sequence,实际项目中最好需要获取id后,删除旧的序列,要不然zk的path会越来越多.

截图

分布式自增序列的实现(一)

相关文章:

  • 2021-12-03
  • 2022-12-23
  • 2022-01-24
  • 2021-07-12
  • 2021-06-01
  • 2021-09-26
  • 2022-12-23
猜你喜欢
  • 2021-11-17
  • 2022-12-23
  • 2022-12-23
  • 2021-08-10
  • 2021-04-06
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案