springboot项目通过雪花算法生成19位数字id

摘要:
但是不常使用的表可以使用自增,常用的表使用雪花算法生成id。

建议:

  • 雪花算法可以用来生成id也可以用来生成订单号。但是不常使用的表可以使用自增,常用的表使用雪花算法生成id。这样效果更好
  • 数据库表Id类型设置为 bigint(否则下面的代码也会报错)

首先生成雪花id,这样虽然可以直接调用也就是通过new这个类的对象来生成,但是因为使用了spring框架,交给容器管理更好,所以下面就通过配置来实现将类注入到容器中

springboot项目通过雪花算法生成19位数字id第1张springboot项目通过雪花算法生成19位数字id第2张
importjava.security.SecureRandom;

public classSnowflakeManager {
    private static final long EPOCH_STAMP = 1262275200000L;
    private static final long SEQUENCE_BIT = 12L;
    private static final long MACHINE_BIT = 5L;
    private static final long DATA_CENTER_BIT = 5L;
    private static final long MAX_SEQUENCE_NUM = -1L ^ (-1L <<SEQUENCE_BIT);
    private static final long MAX_MACHINE_NUM = -1L ^ (-1L <<MACHINE_BIT);
    private static final long MAX_DATA_CENTER_NUM = -1L ^ (-1L <<DATA_CENTER_BIT);
    private static final long MACHINE_LEFT =SEQUENCE_BIT;
    private static final long DATA_CENTER_LEFT = SEQUENCE_BIT +MACHINE_BIT;
    private static final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT +DATA_CENTER_BIT;
    private final longmachineId;
    private final longdataCenterId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeManager(long machineId, longdataCenterId) {
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException(String.format("machine id can't be greater than %d or less than 0", MAX_MACHINE_NUM));
        }
        if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) {
            throw new IllegalArgumentException(String.format("data center id can't be greater than %d or less than 0", MAX_DATA_CENTER_NUM));
        }
        this.machineId =machineId;
        this.dataCenterId =dataCenterId;
    }

    public synchronized long nextValue() throwsException {
        String os = System.getProperty("os.name");
        SecureRandom secureRandom;
        if (os.toLowerCase().startsWith("win")) {
            //windows机器用
            secureRandom =SecureRandom.getInstanceStrong();
        } else{
            //linux机器用
            secureRandom = SecureRandom.getInstance("NativePRNGNonBlocking");
        }
        //SecureRandom secureRandom = SecureRandom.getInstanceStrong();
        long currentTimeMillis = this.currentTimeMillis();
        if(currentTimeMillis < this.lastTimestamp) {
            throw new Exception(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", (this.lastTimestamp-currentTimeMillis)));
        }

        if(this.lastTimestamp ==currentTimeMillis) {
            this.sequence = (this.sequence+1) &MAX_SEQUENCE_NUM;
            if (this.sequence == 0) {
                this.sequence =secureRandom.nextInt(Long.valueOf(SEQUENCE_BIT).intValue());
                currentTimeMillis = this.tilNextMillis(this.lastTimestamp);
            }
        } else{
            this.sequence =secureRandom.nextInt(Long.valueOf(SEQUENCE_BIT).intValue());
        }
        this.lastTimestamp =currentTimeMillis;

        //64 Bit ID (42(Millis)+5(Data Center ID)+5(Machine ID)+12(Repeat Sequence Summation))
        long nextId = ((currentTimeMillis-EPOCH_STAMP) <<TIMESTAMP_LEFT)
                | (this.dataCenterId <<DATA_CENTER_LEFT)
                | (this.machineId <<MACHINE_LEFT)
                | this.sequence;

        returnnextId;
    }

    private long tilNextMillis(longlastTimestamp) {
        long currentTimeMillis = this.currentTimeMillis();
        while (currentTimeMillis <=lastTimestamp) {
            currentTimeMillis = this.currentTimeMillis();
        }
        returncurrentTimeMillis;
    }

    private longcurrentTimeMillis() {
        returnSystem.currentTimeMillis();
    }

    public static void main(String[] args) throwsException {
        SnowflakeManager snowflakeManager = new SnowflakeManager(0L,0L);
        long l =snowflakeManager.nextValue();
        System.out.println(l);
    }
}
View Code
  • 1、因为生成雪花id时要传入两个long型的参数,所以将这两个参数提到配置文件中来
    application.yml (里面的包名改成自己的)
com:
  linshan:
    demo1:
      snowflake:
        machine-id: 1
        data-center-id: 1

我的包结构如下:(可以自己适当调整)

springboot项目通过雪花算法生成19位数字id第3张

  • 2、创建一个类 TestProperties ,来获取配置文件中的信息,一个类 SnowflakeProperties 来存需要传入的两个参数。
    TestProperties
importcom.linshan.demo1.entity.SnowflakeProperties;
importlombok.Data;
importorg.springframework.boot.context.properties.ConfigurationProperties;

@Data
//包名更改成自己的 @ConfigurationProperties(prefix
= "com.linshan.demo1") public classTestProperties { privateSnowflakeProperties snowflake; }

SnowflakeProperties

importlombok.Getter;
importlombok.Setter;

@Getter
@Setter
public classSnowflakeProperties {
    private longmachineId;
    private longdataCenterId;
}
  • 3、创建BossAutoConfiguration
  • 这里注意的是@EnableConfigurationProperties注解的作用是:使使用 @ConfigurationProperties 注解的类生效。
importcom.linshan.demo1.entity.SnowflakeManager;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
importorg.springframework.boot.context.properties.EnableConfigurationProperties;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(TestProperties.class)
public classBossAutoConfiguration {
    @Autowired
    privateTestProperties properties;

    @Bean
    @ConditionalOnMissingBean
    publicSnowflakeManager snowflakeManager() {
        return new SnowflakeManager(this.properties.getSnowflake().getMachineId(), this.properties.getSnowflake().getDataCenterId());
    }
}
  • 4、最后就是直接在需要使用的类中注入即可

springboot项目通过雪花算法生成19位数字id第4张

springboot项目通过雪花算法生成19位数字id第5张

原文入口

免责声明:文章转载自《springboot项目通过雪花算法生成19位数字id》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux下修改用户home目录在App中添加微信分享功能下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

AVR单片机教程——示波器

本文隶属于AVR单片机教程系列。   在用DAC做了一个稍大的项目之后,我们来拿ADC开开刀。在本讲中,我们将了解0.96寸OLED屏,移植著名的U8g2库到我们的开发板上,学习在屏幕上画直线的算法,编写一个示波器程序,使用EEPROM加入人性化功能,最后利用示波器观察555定时器、放大电路、波形变换电路的各种波形。 本讲所需的资料可以在这里下载:提取码6...

【Golang】Go中时间(time)的用法以及gorm处理时间戳

time包提供了时间的显示和测量用的函数。日历的计算采用的是公历。 time 类型 type Time struct { // wall and ext encode the wall time seconds, wall time nanoseconds, // and optional monotonic clock reading in nanose...

Intel Core Microarchitecture Pipeline

Intel微处理器近20年从Pentium发展到Skylake,得益于制作工艺上的巨大发展,处理器的性能得到了非常大的增强,功能模块增多,不过其指令处理pipeline的主干部分算不上有特别大的变化,更多的是为了提高指令的处理速度添加一些模块以及各模块的增强与优化。 本文会以Intel Core微处理器架构为例去了解Intel微处理器pipeline的各个...

SpringBoot 2.x 整合Lombok

Lombok的官方介绍 Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java. Lombok以简单的注解形式来简化java代码,提高开发人员的开发效率 lombok是一个编译级别的插件,...

python --bs4

#https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#attributes &https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/ 属性: 返回值 返回类型 soup.prettify()方法 友好显示,在内容中加入 str...

【BBC micro:bit基础教程】02-micro:bit与人体运动检测传感器

【所需材料】 BBC micro:bit 主板 x 1 Micro USB 线   x 1 能容纳2节7号(AAA)电池的电池盒 x 1 7号(AAA)电池 x 2 人体运动检测传感器 x 1 鳄鱼夹 x 3 【电路接线步骤】 断掉micro:bit与电脑和电池的连接,保证micro:bit处于非供电状态。 用鳄鱼夹将人体运动检测传感器的Powe...