|
@@ -0,0 +1,136 @@
|
|
|
|
+package com.zhentao.util;
|
|
|
|
+
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
+import java.time.ZoneOffset;
|
|
|
|
+
|
|
|
|
+public class SnowflakeIdGenerator {
|
|
|
|
+ // 基础配置(Java 8+)
|
|
|
|
+ private static final long EPOCH = 1288834974657L; // 2010-11-04 00:00:00 UTC
|
|
|
|
+ private static final int DATACENTER_ID_BITS = 5;
|
|
|
|
+ private static final int WORKER_ID_BITS = 5;
|
|
|
|
+ private static final int SEQUENCE_BITS = 12;
|
|
|
|
+ // 位运算掩码
|
|
|
|
+ private static final long DATACENTER_ID_MASK = (1L << DATACENTER_ID_BITS) - 1;
|
|
|
|
+ private static final long WORKER_ID_MASK = (1L << WORKER_ID_BITS) - 1;
|
|
|
|
+ private static final long SEQUENCE_MASK = (1L << SEQUENCE_BITS) - 1;
|
|
|
|
+
|
|
|
|
+ // 位移偏移量
|
|
|
|
+ private static final int WORKER_ID_SHIFT = SEQUENCE_BITS;
|
|
|
|
+ private static final int DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
|
|
|
|
+ private static final int TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
|
|
|
|
+
|
|
|
|
+ private final long datacenterId;
|
|
|
|
+ private final long workerId;
|
|
|
|
+ private long sequence = 0L;
|
|
|
|
+ private long lastTimestamp = -1L;
|
|
|
|
+
|
|
|
|
+ private final Object lock = new Object();
|
|
|
|
+
|
|
|
|
+ public SnowflakeIdGenerator(long datacenterId, long workerId) {
|
|
|
|
+ if ((datacenterId & DATACENTER_ID_MASK) != datacenterId) {
|
|
|
|
+ throw new IllegalArgumentException("DataCenter ID 必须在 0-31 之间");
|
|
|
|
+ }
|
|
|
|
+ if ((workerId & WORKER_ID_MASK) != workerId) {
|
|
|
|
+ throw new IllegalArgumentException("Worker ID 必须在 0-31 之间");
|
|
|
|
+ }
|
|
|
|
+ this.datacenterId = datacenterId;
|
|
|
|
+ this.workerId = workerId;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public synchronized long nextId() {
|
|
|
|
+ long currentTimestamp = timeGen();
|
|
|
|
+
|
|
|
|
+ if (currentTimestamp < lastTimestamp) {
|
|
|
|
+ throw new IllegalStateException(
|
|
|
|
+ String.format("时钟回退 %d 毫秒,禁止生成ID(上次: %d,当前: %d)",
|
|
|
|
+ lastTimestamp - currentTimestamp, lastTimestamp, currentTimestamp));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (currentTimestamp == lastTimestamp) {
|
|
|
|
+ sequence = (sequence + 1) & SEQUENCE_MASK;
|
|
|
|
+ if (sequence == 0) {
|
|
|
|
+ currentTimestamp = waitNextMillis(lastTimestamp);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ sequence = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lastTimestamp = currentTimestamp;
|
|
|
|
+
|
|
|
|
+ return ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) |
|
|
|
|
+ (datacenterId << DATACENTER_ID_SHIFT) |
|
|
|
|
+ (workerId << WORKER_ID_SHIFT) |
|
|
|
|
+ sequence;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private long waitNextMillis(long lastTimestamp) {
|
|
|
|
+ long timestamp = timeGen();
|
|
|
|
+ while (timestamp <= lastTimestamp) {
|
|
|
|
+ timestamp = System.currentTimeMillis(); // 改用更可靠的时间源
|
|
|
|
+ }
|
|
|
|
+ return timestamp;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private long timeGen() {
|
|
|
|
+ return System.currentTimeMillis();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 添加 parseId 方法
|
|
|
|
+ public static SnowflakeMeta parseId(long snowflakeId) {
|
|
|
|
+ long sequence = snowflakeId & SEQUENCE_MASK;
|
|
|
|
+ long workerId = (snowflakeId >> WORKER_ID_SHIFT) & WORKER_ID_MASK;
|
|
|
|
+ long datacenterId = (snowflakeId >> DATACENTER_ID_SHIFT) & DATACENTER_ID_MASK;
|
|
|
|
+ long timestamp = (snowflakeId >> TIMESTAMP_SHIFT) + EPOCH;
|
|
|
|
+
|
|
|
|
+ return new SnowflakeMeta(
|
|
|
|
+ timestamp,
|
|
|
|
+ datacenterId,
|
|
|
|
+ workerId,
|
|
|
|
+ sequence,
|
|
|
|
+ LocalDateTime.ofEpochSecond(timestamp / 1000, 0, ZoneOffset.ofHours(8))
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ public static Long getSnowId(){
|
|
|
|
+ SnowflakeIdGenerator generator=new SnowflakeIdGenerator(1,1);
|
|
|
|
+ Long id=generator.nextId();
|
|
|
|
+ SnowflakeMeta meta=SnowflakeIdGenerator.parseId(id);
|
|
|
|
+ return id;
|
|
|
|
+ }
|
|
|
|
+ // ---------------- 修复:添加完整的getter方法 ----------------
|
|
|
|
+ public static class SnowflakeMeta {
|
|
|
|
+ private final long timestamp;
|
|
|
|
+ private final long datacenterId;
|
|
|
|
+ private final long workerId;
|
|
|
|
+ private final long sequence;
|
|
|
|
+ private final LocalDateTime dateTime;
|
|
|
|
+
|
|
|
|
+ public SnowflakeMeta(long timestamp, long datacenterId, long workerId, long sequence, LocalDateTime dateTime) {
|
|
|
|
+ this.timestamp = timestamp;
|
|
|
|
+ this.datacenterId = datacenterId;
|
|
|
|
+ this.workerId = workerId;
|
|
|
|
+ this.sequence = sequence;
|
|
|
|
+ this.dateTime = dateTime;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 显式定义getter(修复爆红)
|
|
|
|
+ public long getTimestamp() {
|
|
|
|
+ return timestamp;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public long getDatacenterId() {
|
|
|
|
+ return datacenterId;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public long getWorkerId() {
|
|
|
|
+ return workerId;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public long getSequence() {
|
|
|
|
+ return sequence;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public LocalDateTime getDateTime() {
|
|
|
|
+ return dateTime;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|