雪花算法SnowFlake 细致易懂 Java/Springboot实现
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.concurrent.atomic.AtomicLong;
public class SnowflakeIdWorker {
// 初始时间戳
private final static long INITIAL_TIMESTAMP = 1640995200000L; // 假设的初始时间戳
// 机器ID所占的位数
private final static long ID_BITS = 5L;
// 数据中心ID所占的位数
private final static long DATA_CENTER_ID_BITS = 5L;
// 机器ID最大值
private final static long MAX_MACHINE_ID = -1L ^ (-1L << ID_BITS);
// 数据中心ID最大值
private final static long MAX_DATA_CENTER_ID = -1L ^ (-1L << DATA_CENTER_ID_BITS);
// 序列在ID中的位置
private final static long SEQUENCE_BITS = 12L;
// 机器ID偏左移12位
private final static long MACHINE_ID_LEFT = SEQUENCE_BITS;
// 数据中心ID偏左移17位
private final static long DATA_CENTER_ID_LEFT = SEQUENCE_BITS + ID_BITS;
// 时间戳偏左移22位
private final static long TIMESTAMP_LEFT = SEQUENCE_BITS + ID_BITS + DATA_CENTER_ID_BITS;
// 序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
private final static long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS);
// 工作机器ID(0~31)
private long machineId;
// 数据中心ID(0~31)
private long dataCenterId;
// 下一个序列值
private AtomicLong sequence = new AtomicLong(0L);
// 上次生成ID的时间戳
private long lastTimestamp = -1L;
public SnowflakeIdWorker(long machineId, long dataCenterId) {
if (machineId > MAX_MACHINE_ID || machineId < 0) {
throw new IllegalArgumentException("机器ID超出范围");
}
if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
throw new IllegalArgumentException("数据中心ID超出范围");
}
this.machineId = machineId;
this.dataCenterId = dataCenterId;
}
/**
* 创建一个新的ID
*
* @return Snowflake生成的ID
*/
public synchronized long nextId() {
long timestamp = timeGen();
// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退了,这是不允许的。
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format(
"时钟回退,上一个ID生成的时间戳为:%d,现在时间戳为:%d", lastTimestamp, timestamp));
}
// 如果是同一时间生成的,则进行序列号的自增
if (lastTimestamp == timestamp) {
评论已关闭