SpringBoot自定义雪花算法生成ID的实现示例

 更新时间:2025年04月25日 09:57:22   作者:灰_灰丶灰  
雪花算法是一种生成唯一ID的分布式算法,它能生成不重复的、有时间顺序的全局唯一ID,本文主要介绍了SpringBoot自定义雪花算法生成ID的实现示例,具有一定的参考价值,感兴趣的可以了解一下

雪花算法(Snowflake)是一种生成唯一ID的分布式算法,由Twitter推出。它能生成不重复的、有时间顺序的全局唯一ID。一个典型的Snowflake ID由64位组成,通常划分如下:

  • 1位符号位(始终为0,表示正数)
  • 41位时间戳(毫秒级,表示当前时间相对于某个开始时间的偏移)
  • 10位机器标识(通常分为数据中心ID和机器ID)
  • 12位序列号(表示毫秒内的计数器)

下面是一个自定义的雪花算法来生成唯一的ID。这个实现类似于Twitter的Snowflake算法,并考虑到了线程安全。

public class SnowflakeIDGenerator {

    // 起始时间戳(2020-01-01 00:00:00)
    private final long twepoch = 1577836800000L;

    // 每部分占用的位数
    private final long workerIdBits = 5L;
    private final long datacenterIdBits = 5L;
    private final long sequenceBits = 12L;

    // 最大值
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

    // 位移
    private final long workerIdShift = sequenceBits;
    private final long datacenterIdShift = sequenceBits + workerIdBits;
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

    // 掩码
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    private long workerId;
    private long datacenterId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeIDGenerator(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    public synchronized long nextId() {
        long timestamp = timeGen();

        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        return ((timestamp - twepoch) << timestampLeftShift)
                | (datacenterId << datacenterIdShift)
                | (workerId << workerIdShift)
                | sequence;
    }

    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    protected long timeGen() {
        return System.currentTimeMillis();
    }

    public static void main(String[] args) {
        SnowflakeIDGenerator generator = new SnowflakeIDGenerator(1, 1);
        for (int i = 0; i < 10; i++) {
            System.out.println(generator.nextId());
        }
    }
}

说明

  • 初始化参数:

    • twepoch:自定义的起始时间戳(可以是任意过去的时间),确保生成的ID是唯一且有序的。
    • workerIdBits 和 datacenterIdBits:分别表示工作节点ID和数据中心ID的位数(通常为5位)。
    • sequenceBits:表示序列号的位数(通常为12位)。
  • 最大值计算:

    • maxWorkerId 和 maxDatacenterId:根据位数计算出的最大值,确保ID在合理范围内。
  • 位移量:

    • workerIdShiftdatacenterIdShifttimestampLeftShift:用于将各部分数据移到正确的位置。
  • 掩码:

    • sequenceMask:确保序列号在0到4095之间循环。
  • 方法:

    • nextId:生成唯一ID,使用同步块确保线程安全。
    • tilNextMillis:等待直到下一毫秒。
    • timeGen:获取当前时间戳。

使用示例

运行上述代码,你会看到生成的唯一ID,它们是按时间顺序递增的,每个ID包含了时间戳、数据中心ID、工作节点ID和序列号的信息。

到此这篇关于SpringBoot自定义雪花算法生成ID的实现示例的文章就介绍到这了,更多相关SpringBoot 雪花算法生成ID内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring 源码解析CommonAnnotationBeanPostProcessor

    Spring 源码解析CommonAnnotationBeanPostProcessor

    这篇文章主要为大家介绍了Spring 源码解析CommonAnnotationBeanPostProcessor示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • 全方位讲解Java的面向对象编程思想

    全方位讲解Java的面向对象编程思想

    这篇文章主要介绍了Java的面相对象编程思想,包括类对象方法和封装继承多态等各个方面的OOP基本要素,非常推荐,需要的朋友可以参考下
    2016-01-01
  • Spring boot 配置多个redis的方法示例

    Spring boot 配置多个redis的方法示例

    这篇文章主要介绍了Spring boot 配置多个redis的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • SpringBoot起步依赖和自动配置基本介绍

    SpringBoot起步依赖和自动配置基本介绍

    这篇文章主要介绍了SpringBoot起步依赖和自动配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • 全面解释java中StringBuilder、StringBuffer、String类之间的关系

    全面解释java中StringBuilder、StringBuffer、String类之间的关系

    String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间,StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象,StringBuffer和StringBuilder类功能基本相似
    2013-01-01
  • IDEA编译时报常量字符串过长的解决办法

    IDEA编译时报常量字符串过长的解决办法

    本文主要介绍了IDEA编译时报常量字符串过长的解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • java基于C/S模式实现聊天程序(服务器)

    java基于C/S模式实现聊天程序(服务器)

    这篇文章主要为大家详细介绍了java基于C/S模式实现聊天程序的服务器篇,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • 使用Spring注入Hibernate验证框架

    使用Spring注入Hibernate验证框架

    这篇文章主要介绍了使用Spring注入Hibernate验证框架方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 详细介绍Java后端API接口开发规范

    详细介绍Java后端API接口开发规范

    在Java后端开发中,API接口的设计与开发至关重要,本文详细介绍了命名规范、接收参数规范、参数检验、接收方式规范、异常类处理、统一返回格式以及幂等性等方面的开发规范,提供了实际代码示例,需要的朋友可以参考下
    2024-10-10
  • Java后端请求接收多个对象入参的数据方法(推荐)

    Java后端请求接收多个对象入参的数据方法(推荐)

    本文介绍了如何使用SpringBoot框架接收多个对象作为HTTP请求的入参,通过创建数据模型、DTO类和Controller,我们可以轻松处理复杂的请求数据
    2024-11-11

最新评论