springboot雪花id
时间: 2025-03-27 15:19:07 浏览: 42
### Spring Boot 中实现雪花算法生成唯一 ID
在 Spring Boot 应用程序中集成雪花算法来生成唯一的全局 ID 是一种常见做法。通过这种方式可以确保即使在高并发场景下也能快速可靠地获取到不重复的 ID。
#### 雪花算法简介
SnowFlake 算法由 Twitter 提出,采用了一个 64bit 的 Long 类型数据结构用于表示唯一 ID[^2]。具体位分配如下:
| 字段 | 描述 |
| --- | --- |
| 符号位 (1 bit) | 总是0, 表示正数 |
| 时间戳 (41 bits) | 记录毫秒级时间偏移量 |
| 数据中心ID (5 bits) | 支持最多31个数据中心 |
| 工作机器ID (5 bits) | 同一数据中心内支持最多31台服务器 |
| 自增序列号 (12 bits) | 单机每毫秒内的计数值 |
这种设计使得生成出来的 ID 不仅具有全局唯一性而且还能保持一定顺序特性,在数据库索引方面表现良好。
#### 实现步骤
为了方便开发者使用,这里提供了一种基于 Java 编写的 SnowflakeIdWorker 类实现方式,并将其封装成工具类以便于调用。
```java
package com.example.demo.utils;
import org.springframework.stereotype.Component;
@Component
public class IdGenerator {
private final static long twepoch = 1288834974657L; // 起始的时间戳
private final static int workerIdBits = 5;
private final static int datacenterIdBits = 5;
private final static long maxWorkerId = ~(-1L << workerIdBits);
private final static long maxDataCenterId = ~(-1L << datacenterIdBits);
private final static int sequenceBits = 12;
private final static long workerIdShift = sequenceBits;
private final static long datacenterIdShift = sequenceBits + workerIdBits;
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final static long sequenceMask = ~(-1L << sequenceBits);
private long workerId;
private long datacenterId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public IdGenerator(long workerId, long datacenterId){
if(workerId > maxWorkerId || workerId < 0){
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0",maxWorkerId));
}
if(datacenterId > maxDataCenterId || datacenterId < 0){
throw new IllegalArgumentException(String.format("data center Id can't be greater than %d or less than 0",maxDataCenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
protected synchronized long nextId(){
long timestamp = timeGen();
if(timestamp < lastTimestamp){
try{
throw new Exception("Clock moved backwards. Refusing to generate id");
}catch(Exception e){
System.err.println(e.getMessage());
}
}
if(lastTimestamp == timestamp){
sequence = (sequence + 1) & sequenceMask;
if(sequence == 0){
timestamp = tilNextMillis(lastTimestamp);
}
}else{
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - twepoch) << timestampLeftShift) |
(datacenterId << datacenterIdShift) |
(workerId << workerIdShift) |
sequence;
}
private long tilNextMillis(final long lastTimestamp){
long timestamp = timeGen();
while (timestamp <= lastTimestamp){
timestamp = timeGen();
}
return timestamp;
}
private long timeGen(){
return System.currentTimeMillis();
}
}
```
上述代码实现了基本的雪球算法逻辑并提供了 `nextId()` 方法用来获取新的唯一 ID。需要注意的是实际部署时还需要考虑跨节点同步等问题以防止冲突发生。
对于 Spring Boot 应用来说可以直接注入此组件并通过方法调用来获得所需 ID:
```java
@Autowired
private IdGenerator idGenerator;
// 使用地方直接调用即可得到新id
Long uniqueId = idGenerator.nextId();
```
此外还可以进一步优化该方案比如引入 Redis 或 Zookeeper 来管理 Worker 和 Data Center IDs 分配从而更好地适应大规模集群环境下的需求。
阅读全文
相关推荐


















