0
点赞
收藏
分享

微信扫一扫

详解Java雪花算法

陌岛 2023-08-16 阅读 46

详解Java雪花算法

简介

雪花算法(Snowflake)是一种用于生成全局唯一标识符的算法,最初由Twitter公司开发。它基于时间戳、数据中心ID和工作节点ID,通过将这些信息进行位运算和移位操作来生成一个64位的唯一ID。

算法原理

雪花算法的64位ID由以下几个部分组成:

  1. 符号位:最高位是符号位,始终为0。
  2. 时间戳:41位,精确到毫秒级,能表示的时间范围为2^41 - 1毫秒,大约69年。
  3. 数据中心ID:5位,用于区分不同的数据中心,最多支持2^5个数据中心。
  4. 工作节点ID:5位,用于区分同一数据中心中的不同工作节点,最多支持2^5个工作节点。
  5. 序列号:12位,用于生成同一毫秒内的不同ID,最多支持2^12个ID。

状态图

以下是雪花算法的状态图:

stateDiagram
    [*] --> 初始化
    初始化 --> 工作中
    工作中 --> 生成ID
    生成ID --> 工作中

代码示例

下面是一个使用Java实现的雪花算法示例:

public class SnowflakeIdGenerator {
    private static final long START_TIMESTAMP = 1609459200000L; // 2021-01-01 00:00:00
    private static final long DATA_CENTER_ID_BITS = 5L;
    private static final long WORKER_ID_BITS = 5L;
    private static final long SEQUENCE_BITS = 12L;
    private static final long MAX_DATA_CENTER_ID = -1L ^ (-1L << DATA_CENTER_ID_BITS);
    private static final long MAX_WORKER_ID = -1L ^ (-1L << WORKER_ID_BITS);
    private static final long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS);

    private final long dataCenterId;
    private final long workerId;
    private long lastTimestamp = -1L;
    private long sequence = 0L;

    public SnowflakeIdGenerator(long dataCenterId, long workerId) {
        if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
            throw new IllegalArgumentException("Data center ID can't be greater than " + MAX_DATA_CENTER_ID + " or less than 0");
        }
        if (workerId > MAX_WORKER_ID || workerId < 0) {
            throw new IllegalArgumentException("Worker ID can't be greater than " + MAX_WORKER_ID + " or less than 0");
        }
        this.dataCenterId = dataCenterId;
        this.workerId = workerId;
    }

    public synchronized long generateId() {
        long timestamp = System.currentTimeMillis();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate ID");
        }
        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & SEQUENCE_MASK;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        return ((timestamp - START_TIMESTAMP) << (DATA_CENTER_ID_BITS + WORKER_ID_BITS + SEQUENCE_BITS))
                | (dataCenterId << (WORKER_ID_BITS + SEQUENCE_BITS))
                | (workerId << SEQUENCE_BITS)
                | sequence;
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }
}

使用示例

下面是一个使用雪花算法生成唯一ID的示例:

public class Main {
    public static void main(String[] args) {
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1); // 使用数据中心ID为1,工作节点ID为1

        long id = idGenerator.generateId();
        System.out.println("Generated ID: " + id);
    }
}

运行上面的代码会输出一个唯一ID。

总结

雪花算法是一种用于生成全局唯一标识符的算法,它通过时间戳、数据中心ID和工作节点ID生成一个64位的唯一ID。使用Java实现雪花算法可以方便地生成全局唯一的ID,可以在分布式系统

举报

相关推荐

0 条评论