0
点赞
收藏
分享

微信扫一扫

java 雪花算法

Java雪花算法实现

简介

雪花算法(Snowflake)是Twitter开源的一种分布式ID生成算法,它可以保证在分布式系统中生成唯一的ID。该算法生成的ID是一个64位的整数,由以下几部分组成:时间戳、工作机器ID、数据中心ID和序列号。

在本文中,我将详细介绍如何在Java中实现雪花算法,并提供每一步所需的代码及其注释。

实现步骤

下表展示了实现雪花算法所需的步骤及每一步需要做的事情。

步骤 描述
1 定义雪花算法的参数
2 获取当前时间戳
3 判断时间戳是否小于上次生成ID的时间戳
4 生成唯一ID
5 更新上次生成ID的时间戳
6 返回生成的唯一ID

接下来,我将详细解释每一步所需的代码及其注释。

1. 定义雪花算法的参数

private final long startTime = 1609459200000L; // 设置起始时间戳,这里选择2021-01-01 00:00:00的时间戳
private final long workerIdBits = 5L; // 工作机器ID所占的位数
private final long datacenterIdBits = 5L; // 数据中心ID所占的位数
private final long maxWorkerId = -1L ^ (-1L << workerIdBits); // 支持的最大工作机器ID,结果为31
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 支持的最大数据中心ID,结果为31
private final long sequenceBits = 12L; // 序列号所占的位数
private final long workerIdShift = sequenceBits; // 工作机器ID左移位数
private final long datacenterIdShift = sequenceBits + workerIdBits; // 数据中心ID左移位数
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; // 时间戳左移位数
private final long sequenceMask = -1L ^ (-1L << sequenceBits); // 序列号的掩码,结果为4095

上述代码定义了雪花算法的参数,包括起始时间戳、工作机器ID位数、数据中心ID位数、最大工作机器ID、最大数据中心ID、序列号位数、工作机器ID左移位数、数据中心ID左移位数、时间戳左移位数和序列号掩码。

2. 获取当前时间戳

private long getTimeStamp() {
    return System.currentTimeMillis();
}

上述代码使用System.currentTimeMillis()方法获取当前的时间戳。

3. 判断时间戳是否小于上次生成ID的时间戳

private long tilNextMillis(long lastTimestamp) {
    long timestamp = getTimeStamp();
    while (timestamp <= lastTimestamp) {
        timestamp = getTimeStamp();
    }
    return timestamp;
}

上述代码判断当前时间戳是否小于上次生成ID的时间戳,如果是,则持续获取新的时间戳,直到大于上次生成ID的时间戳为止。

4. 生成唯一ID

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

    // 如果当前时间小于上次生成ID的时间戳,则需要等待
    if (timestamp < lastTimestamp) {
        timestamp = tilNextMillis(lastTimestamp);
    }

    // 如果是同一毫秒内的生成的ID,则需要增加序列号
    if (timestamp == lastTimestamp) {
        sequence = (sequence + 1) & sequenceMask;
        if (sequence == 0) {
            timestamp = tilNextMillis(lastTimestamp);
        }
    } else {
        sequence = 0;
    }

    // 更新上次生成ID的时间戳
    lastTimestamp = timestamp;

    // 生成ID
    long id = ((timestamp - startTime) << timestampLeftShift)
            | (datacenterId << datacenterIdShift)
            | (workerId << workerIdShift)
            | sequence;

    return id;
}

上述代码生成唯一ID的过程包括以下几个

举报

相关推荐

0 条评论