springBoot中雪花算术法

在 Spring Boot 中,雪花算法(Snowflake Algorithm)通常指的是 Twitter 开发的一种分布式唯一 ID 生成算法。它被广泛用于分布式系统中生成全局唯一的 ID,尤其是在高并发场景下。雪花算法生成的 ID 是一个 64 位的长整型数字,具有时间有序性和唯一性。

虽然 Spring Boot 本身没有直接内置雪花算法的实现,但你可以通过自定义代码或引入第三方库来实现它。下面我将解释雪花算法的原理,并提供一个在 Spring Boot 中实现的示例。


雪花算法原理

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

  1. **1 位符号位**:通常为 0,表示正数。

  2. **41 位时间戳**:表示毫秒级时间戳,通常是当前时间与某个起始时间(epoch)的差值,可支持约 69 年的时间范围。

  3. **10 位机器 ID**:表示机器或进程的标识,支持 1024 个节点。

  4. **12 位序列号**:每毫秒内的自增序列号,支持每毫秒生成 4096 个 ID。

生成的 ID 结构如下:

```

0 | 41-bit timestamp | 10-bit worker ID | 12-bit sequence

```

优点:

  • 高性能、高并发下仍能保证唯一性。

  • ID 是时间有序的,便于排序和存储。

  • 不依赖数据库等外部系统。


在 Spring Boot 中实现雪花算法

以下是一个简单的雪花算法实现示例,你可以将其集成到 Spring Boot 项目中。

1. 创建雪花算法工具类

```java

public class SnowflakeIdGenerator {

// 起始时间戳 (例如 2023-01-01 00:00:00)

private static final long START_TIMESTAMP = 1672531200000L;

// 各部分位数

private static final long WORKER_ID_BITS = 10L; // 机器 ID 占 10 位

private static final long SEQUENCE_BITS = 12L; // 序列号占 12 位

// 最大值

private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS); // 1023

private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS); // 4095

// 位移量

private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;

private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;

private long workerId; // 机器 ID

private long sequence = 0L; // 序列号

private long lastTimestamp = -1L; // 上次生成 ID 的时间戳

public SnowflakeIdGenerator(long workerId) {

if (workerId > MAX_WORKER_ID || workerId < 0) {

throw new IllegalArgumentException("Worker ID must be between 0 and " + MAX_WORKER_ID);

}

this.workerId = workerId;

}

// 生成下一个 ID

public synchronized long nextId() {

long currentTimestamp = System.currentTimeMillis();

// 时钟回拨检查

if (currentTimestamp < lastTimestamp) {

throw new RuntimeException("Clock moved backwards. Refusing to generate ID.");

}

// 如果是同一毫秒内,序列号自增

if (currentTimestamp == lastTimestamp) {

sequence = (sequence + 1) & MAX_SEQUENCE;

// 序列号溢出,等待下一毫秒

if (sequence == 0) {

currentTimestamp = waitNextMillis(currentTimestamp);

}

} else {

sequence = 0L; // 新毫秒,序列号重置

}

lastTimestamp = currentTimestamp;

// 组合 ID

return ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT) |

(workerId << WORKER_ID_SHIFT) |

sequence;

}

// 等待下一毫秒

private long waitNextMillis(long currentTimestamp) {

long timestamp = System.currentTimeMillis();

while (timestamp <= currentTimestamp) {

timestamp = System.currentTimeMillis();

}

return timestamp;

}

}

```

2. 在 Spring Boot 中使用

将上述工具类注入到 Spring Boot 的服务中,例如:

```java

import org.springframework.stereotype.Service;

@Service

public class IdGeneratorService {

private final SnowflakeIdGenerator idGenerator;

public IdGeneratorService() {

// 假设 workerId 为 1,可以通过配置动态设置

this.idGenerator = new SnowflakeIdGenerator(1L);

}

public long generateId() {

return idGenerator.nextId();

}

}

```

3. 调用示例

在 Controller 中调用服务生成 ID:

```java

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

public class IdController {

@Autowired

private IdGeneratorService idGeneratorService;

@GetMapping("/generate-id")

public long generateId() {

return idGeneratorService.generateId();

}

}

```

4. 配置 workerId

在分布式系统中,`workerId` 需要唯一,可以通过配置文件或机器标识动态分配。例如,使用 Spring Boot 的 `application.properties`:

```properties

snowflake.worker-id=1

```

然后在服务中读取:

```java

@Service

public class IdGeneratorService {

private final SnowflakeIdGenerator idGenerator;

@Autowired

public IdGeneratorService(@Value("${snowflake.worker-id}") long workerId) {

this.idGenerator = new SnowflakeIdGenerator(workerId);

}

public long generateId() {

return idGenerator.nextId();

}

}

```


使用第三方库

如果你不想自己实现雪花算法,可以使用现成的库,例如:

  • **Hutool**:一个流行的 Java 工具库,内置了雪花算法实现。

```xml

<dependency>

<groupId>cn.hutool</groupId>

<artifactId>hutool-all</artifactId>

<version>5.8.11</version>

</dependency>

```

使用示例:

```java

import cn.hutool.core.lang.Snowflake;

Snowflake snowflake = new Snowflake(1, 1); // workerId, dataCenterId

long id = snowflake.nextId();

```

  • **MyBatis-Plus**:如果你的项目使用 MyBatis-Plus,它也提供了雪花算法的支持。

注意事项

  1. **时钟回拨问题**:如果服务器时间被调整,可能导致 ID 重复。需要在代码中处理时钟回拨。

  2. **机器 ID 分配**:在分布式环境中,确保每个节点的 `workerId` 唯一。

  3. **性能**:雪花算法适合高并发场景,但序列号耗尽后需等待下一毫秒。

希望这个解答对你有帮助!如果需要更详细的代码或优化建议,请告诉我。

相关推荐
LiRuiJie13 分钟前
深入剖析Spring Boot / Spring 应用中可自定义的扩展点
java·spring boot·spring
Funcy28 分钟前
XxlJob 源码分析03:执行器启动流程
后端
豌豆花下猫2 小时前
Python 潮流周刊#118:Python 异步为何不够流行?(摘要)
后端·python·ai
尚学教辅学习资料2 小时前
Ruoyi-vue-plus-5.x第五篇Spring框架核心技术:5.1 Spring Boot自动配置
vue.js·spring boot·spring
晚安里3 小时前
Spring 框架(IoC、AOP、Spring Boot) 的必会知识点汇总
java·spring boot·spring
秋难降3 小时前
SQL 索引突然 “罢工”?快来看看为什么
数据库·后端·sql
上官浩仁3 小时前
springboot ioc 控制反转入门与实战
java·spring boot·spring
Access开发易登软件4 小时前
Access开发导出PDF的N种姿势,你get了吗?
后端·低代码·pdf·excel·vba·access·access开发
叫我阿柒啊4 小时前
从Java全栈到前端框架:一位程序员的实战之路
java·spring boot·微服务·消息队列·vue3·前端开发·后端开发
中国胖子风清扬4 小时前
Rust 序列化技术全解析:从基础到实战
开发语言·c++·spring boot·vscode·后端·中间件·rust