您的位置:

Java实现高效雪花算法生成唯一ID

一、雪花算法介绍

雪花算法是Twitter公司开源的一种用于生成全局唯一ID的算法,它可以保证在分布式的情况下生成唯一ID,解决了传统的递增ID在分布式场景下可能重复的问题。

雪花算法生成的ID是一个64位的长整型,由以下几部分构成:

  1. 时间戳
  2. 机器ID
  3. 序列号

其中,时间戳占用41位,可以表示的时间范围为2^41/(1000*60*60*24*365),大约为69年。机器ID占用10位,可以表示的最大机器数为2^10-1,即1023个。序列号占用12位,可以表示的最大序号数为2^12-1,即4095个。

二、Java实现雪花算法

1、时间戳

首先,我们需要获取当前时间的时间戳。Java中可以使用System.currentTimeMillis()方法获取当前时间戳,不过它只能精确到毫秒级别,为了让我们的ID更加唯一,我们可以使用System.nanoTime()方法获取更加精确的时间戳,精确到纳秒级别。


/**
 * 获取当前时间戳,精确到纳秒级别
 * @return 当前时间戳(毫秒+纳秒)
 */
private static long getCurrentTimestamp() {
    long timestamp = System.nanoTime();
    return (timestamp - START_TIMESTAMP) / 1000000;
}

其中,START_TIMESTAMP是一个固定时间戳,用于计算时间戳的相对值。由于时间戳只占用了41位,所以时间戳的范围是有限的,为了避免时间戳满足之后,冲突概率变高的问题,我们可以将START_TIMESTAMP设置为一个固定的值,比如2018年1月1日。

2、机器ID

雪花算法中,机器ID是用于指示不同机器的一个标识符。在分布式系统中,不同的机器需要有不同的机器ID。可以通过配置文件等方式来获取机器ID,也可以使用网卡MAC地址等实际唯一的标识符来获取。


/**
 * 获取机器ID,可以根据实际情况进行获取
 * @return 机器ID
 */
private static long getMachineId() {
    // TODO 根据实际情况获取机器ID
    return 1;
}

3、序列号

序列号用于保证同一时间内,同一台机器生成不同的ID。为了避免序列号重复,我们需要在同一毫秒内,使用不同的序列号。另外,由于序列号只占用了12位,所以最多可以有4095个序列号,为了避免序列号使用完之后,需要等待到下一毫秒,我们可以将序列号的初始值设置为一个随机数。


/**
 * 获取序列号,同一毫秒内生成不同的序列号
 * @return 序列号
 */
private static long getSequence() {
    long sequence = sequenceGenerator.getAndIncrement();
    return sequence % SEQUENCE_LIMIT;
}

其中,sequenceGenerator是一个AtomicLong类型的变量,用于产生序列号,这个变量在程序启动时,会被初始化为一个随机数,用于保证每次重启程序时,序列号不会从0开始计数。

三、Java实现雪花算法示例代码

下面是一个完整的Java实现雪花算法的示例代码:


/**
 * 雪花算法生成全局唯一ID
 */
public class SnowflakeIdGenerator {
    // 起始的时间戳:2018-01-01
    private static final long START_TIMESTAMP = 1514736000000L;
    // 机器ID所占的位数
    private static final long MACHINE_ID_BITS = 10L;
    // 序列号所占的位数
    private static final long SEQUENCE_BITS = 12L;
    // 支持的最大机器ID,结果是1023
    private static final long MAX_MACHINE_ID = ~(-1L << MACHINE_ID_BITS);
    // 支持的最大序列号,结果是4095
    private static final long SEQUENCE_LIMIT = ~(-1L << SEQUENCE_BITS);
    // 机器ID向左移12位
    private static final long MACHINE_ID_SHIFT = SEQUENCE_BITS;
    // 时间戳向左移22位
    private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS;
    // 机器ID
    private static long machineId;
    // 序列号生成器
    private static AtomicLong sequenceGenerator = new AtomicLong(new Random().nextInt(100));
    
    /**
     * 初始化机器ID,可以根据实际情况进行初始化
     */
    public static void initMachineId() {
        SnowflakeIdGenerator.machineId = getMachineId();
        if(machineId > MAX_MACHINE_ID || machineId < 0) {
            throw new IllegalArgumentException("MachineId can't be greater than " + MAX_MACHINE_ID + " or less than 0.");
        }
    }
    
    /**
     * 生成唯一ID
     * @return 返回64位的唯一ID
     */
    public static synchronized long generateId() {
        long timestamp = getCurrentTimestamp();
        if(timestamp < 0) {
            throw new IllegalStateException("Clock moved backwards, refuse to generate id.");
        }
        
        long sequence = getSequence();
        long id = ((timestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT) |
                (machineId << MACHINE_ID_SHIFT) |
                sequence;
        return id;
    }
    
    /**
     * 获取当前时间戳,精确到纳秒级别
     * @return 当前时间戳(毫秒+纳秒)
     */
    private static long getCurrentTimestamp() {
        long timestamp = System.nanoTime();
        return (timestamp - START_TIMESTAMP) / 1000000;
    }
    
    /**
     * 获取机器ID,可以根据实际情况进行获取
     * @return 机器ID
     */
    private static long getMachineId() {
        // TODO 根据实际情况获取机器ID
        return 1;
    }
    
    /**
     * 获取序列号,同一毫秒内生成不同的序列号
     * @return 序列号
     */
    private static long getSequence() {
        long sequence = sequenceGenerator.getAndIncrement();
        return sequence % SEQUENCE_LIMIT;
    }
}
Java实现高效雪花算法生成唯一ID

2023-05-19
雪花ID生成规则

2023-05-20
雪花ID生成器

2023-05-20
MySQL雪花算法ID的详细阐述

2023-05-20
实现高效加密!打造全能雪花算法工具类

2023-05-19
雪花算法id的多方面阐述

2023-05-21
c语言下雪效果,c语言雪花算法

2022-11-26
js雪花代码,雪花算法js

本文目录一览: 1、求网页飘雪花源代码 2、网页飘雪花的代码是什么 3、Dreamweaver海报首页怎样做出雪花飘 4、淘宝里首页飘雪花 怎么弄啊 js代码放在哪里啊 本人小白 希望大神详解....

2023-12-08
js网页背景雪花(js实现雪花飘落特效)

本文目录一览: 1、淘宝里首页飘雪花 怎么弄啊 js代码放在哪里啊 本人小白 希望大神详解..... 2、利用JS给网页添加雪花飘落的效果 3、怎么让网页上飘着雪花 淘宝里首页飘雪花 怎么弄啊 js代

2023-12-08
印象笔记记录java学习(Java成长笔记)

2022-11-12
Java生成唯一ID的多方面探讨

2023-05-18
python原根生成算法,python雪花算法生成id

2022-11-19
雪花飘落js代码用图片,h5雪花飘落代码

2022-11-24
java方法整理笔记(java总结)

2022-11-08
使用uniqid函数生成唯一ID

2023-05-11
如何生成唯一的32位ID标识符

2023-05-19
使用Python生成唯一ID的方法

2023-05-10
使用uniqid()函数生成唯一ID

2023-05-11
mysql唯一值创建代码,mysql生成唯一id

2022-11-23
java学习笔记(java初学笔记)

2022-11-14