当前位置: 首页 > news >正文

生产级的雪花算法

非常棒的需求!我们来对之前的 生产级 Snowflake 雪花算法 进行一次 全面升级,打造一个 企业级、可插拔、支持自动配置、动态分配 ID、暴露 REST API 和 Prometheus 监控指标 的完整解决方案。


✅ 目标功能

功能技术实现
✅ Spring Boot 自动配置@ConfigurationProperties + spring.factories
✅ 支持 Nacos / ZooKeeper 动态分配 workerId使用 nacos-api 或 curator-framework
✅ REST API 获取 ID/api/id 接口
✅ Prometheus 监控指标集成 micrometer,暴露 ID 生成速率、时钟回拨次数等
✅ 高可用与容错支持本地缓存 workerId、降级策略
✅ 日志 + 健康检查集成 Actuator

📦 项目结构(Spring Boot)

bash

深色版本

src/
├── main/
│   ├── java/
│   │   └── com.example.snowflake/
│   │       ├── SnowflakeAutoConfiguration.java       # 自动装配
│   │       ├── SnowflakeProperties.java              # 配置类
│   │       ├── SnowflakeIdGenerator.java             # 核心生成器
│   │       ├── registry/NacosWorkerIdAllocator.java  # Nacos 分配器
│   │       ├── registry/ZookeeperWorkerIdAllocator.java # ZK 分配器
│   │       ├── web/IdController.java                 # REST API
│   │       ├── metrics/SnowflakeMetrics.java         # 指标统计
│   │       └── SnowflakeApplication.java
│   └── resources/
│       ├── application.yml
│       └── META-INF/spring.factories

✅ 1. Maven 依赖(pom.xml

xml

深色版本

<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Micrometer for Prometheus --><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- Nacos Config(可选) --><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>2.4.1</version><optional>true</optional></dependency><!-- ZooKeeper(可选) --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>5.2.1</version><optional>true</optional></dependency><!-- FastJSON(日志用) --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency>
</dependencies>

✅ 2. 配置类 SnowflakeProperties.java

java

深色版本

import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "snowflake")
public class SnowflakeProperties {private long datacenterId = 1L;private Long workerId; // 可为空,由注册中心分配private String registryType; // "nacos", "zookeeper", "none"private String nacosServerAddr = "localhost:8848";private String zookeeperConnectString = "localhost:2181";private long epoch = 1288834974657L; // Twitter epoch// Getters and Setterspublic long getDatacenterId() { return datacenterId; }public void setDatacenterId(long datacenterId) { this.datacenterId = datacenterId; }public Long getWorkerId() { return workerId; }public void setWorkerId(Long workerId) { this.workerId = workerId; }public String getRegistryType() { return registryType; }public void setRegistryType(String registryType) { this.registryType = registryType; }public String getNacosServerAddr() { return nacosServerAddr; }public void setNacosServerAddr(String nacosServerAddr) { this.nacosServerAddr = nacosServerAddr; }public String getZookeeperConnectString() { return zookeeperConnectString; }public void setZookeeperConnectString(String zookeeperConnectString) { this.zookeeperConnectString = zookeeperConnectString; }public long getEpoch() { return epoch; }public void setEpoch(long epoch) { this.epoch = epoch; }
}

✅ 3. 核心生成器 SnowflakeIdGenerator.java

java

深色版本

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;public class SnowflakeIdGenerator {private static final Logger log = LoggerFactory.getLogger(SnowflakeIdGenerator.class);private final long datacenterId;private final long workerId;private final long epoch;private long lastTimestamp = -1L;private long sequence = 0L;// Micrometer 指标private final Counter idCounter;private final Counter clockBackwardCounter;public SnowflakeIdGenerator(SnowflakeProperties props, MeterRegistry registry) {this.datacenterId = props.getDatacenterId();this.workerId = allocateWorkerId(props);this.epoch = props.getEpoch();Assert.isTrue(this.datacenterId >= 0 && this.datacenterId <= 31, "Datacenter ID must be between 0 and 31");Assert.isTrue(this.workerId >= 0 && this.workerId <= 31, "Worker ID must be between 0 and 31");// 注册指标this.idCounter = Counter.builder("snowflake_ids_generated").description("Total number of Snowflake IDs generated").register(registry);this.clockBackwardCounter = Counter.builder("snowflake_clock_backward_events").description("Number of clock backward events").register(registry);log.info("Snowflake ID Generator initialized. DatacenterId={}, WorkerId={}", datacenterId, workerId);}public synchronized long nextId() {long timestamp = System.currentTimeMillis();if (timestamp < lastTimestamp) {clockBackwardCounter.increment();log.error("Clock is moving backwards. Rejecting request to generate ID.");throw new RuntimeException("Clock moved backwards. Refusing to generate id.");}if (timestamp == lastTimestamp) {sequence = (sequence + 1) & 0xFFF; // 12 bitsif (sequence == 0) {timestamp = waitNextMillis(lastTimestamp);}} else {sequence = Math.random() * 100; // 随机偏移}lastTimestamp = timestamp;long id = ((timestamp - epoch) << 22)| (datacenterId << 17)| (workerId << 12)| sequence;idCounter.increment(); // 统计生成数量return id;}private long waitNextMillis(long last) {long timestamp;do {timestamp = System.currentTimeMillis();} while (timestamp <= last);return timestamp;}private long allocateWorkerId(SnowflakeProperties props) {// 如果配置了 workerId,直接使用if (props.getWorkerId() != null) {return props.getWorkerId();}String type = props.getRegistryType();if ("nacos".equalsIgnoreCase(type)) {return NacosWorkerIdAllocator.allocate(props.getNacosServerAddr());} else if ("zookeeper".equalsIgnoreCase(type)) {return ZookeeperWorkerIdAllocator.allocate(props.getZookeeperConnectString());} else {return autoGenerateWorkerId(); // 默认基于 IP}}private long autoGenerateWorkerId() {try {String ip = java.net.InetAddress.getLocalHost().getHostAddress();String[] parts = ip.split("\\.");int lastOctet = Integer.parseInt(parts[parts.length - 1]);return lastOctet & 31;} catch (Exception e) {return new java.util.Random().nextInt(32);}}
}

✅ 4. Nacos 分配器(NacosWorkerIdAllocator.java

java

深色版本

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;public class NacosWorkerIdAllocator {private static final String GROUP = "SNOWFLAKE";private static final String DATA_ID_PREFIX = "worker-id-";public static long allocate(String serverAddr) {String ip;try {ip = java.net.InetAddress.getLocalHost().getHostAddress();} catch (Exception e) {ip = "127.0.0.1";}String dataId = DATA_ID_PREFIX + ip.replace(".", "-");try {ConfigService configService = NacosFactory.createConfigService(serverAddr);String workerIdStr = configService.getConfig(dataId, GROUP, 5000);if (workerIdStr != null && !workerIdStr.isEmpty()) {return Long.parseLong(workerIdStr.trim());} else {// 未分配,尝试发布一个新 ID(0~31)for (int i = 0; i < 32; i++) {if (configService.publishConfig(dataId, GROUP, String.valueOf(i))) {return i;}}throw new RuntimeException("No available workerId in Nacos");}} catch (NacosException e) {throw new RuntimeException("Failed to allocate workerId from Nacos", e);}}
}

✅ 5. ZooKeeper 分配器(ZookeeperWorkerIdAllocator.java

java

深色版本

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;public class ZookeeperWorkerIdAllocator {private static final String ZK_PATH_PREFIX = "/snowflake/worker-id/";public static long allocate(String connectString) {CuratorFramework client = CuratorFrameworkFactory.newClient(connectString,new ExponentialBackoffRetry(1000, 3));client.start();try {String ip = java.net.InetAddress.getLocalHost().getHostAddress();String path = ZK_PATH_PREFIX + ip;// 尝试创建临时节点存储 workerIdfor (int i = 0; i < 32; i++) {try {client.create().withMode(org.apache.zookeeper.CreateMode.EPHEMERAL).forPath(path, String.valueOf(i).getBytes());return i;} catch (Exception e) {// 已存在,尝试下一个}}throw new RuntimeException("No available workerId in ZooKeeper");} catch (Exception e) {throw new RuntimeException("ZooKeeper allocation failed", e);} finally {client.close();}}
}

✅ 6. REST API 控制器 IdController.java

java

深色版本

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class IdController {private final SnowflakeIdGenerator idGenerator;public IdController(SnowflakeIdGenerator idGenerator) {this.idGenerator = idGenerator;}@GetMapping("/api/id")public Object getId() {long id = idGenerator.nextId();return new Response(id);}@GetMapping("/api/id/info")public Object getInfo() {return new Response("Snowflake Service Running");}static class Response {private final long id;private final String message;public Response(long id) {this.id = id;this.message = null;}public Response(String message) {this.id = -1;this.message = message;}// getters...public long getId() { return id; }public String getMessage() { return message; }}
}

✅ 7. 自动配置类 SnowflakeAutoConfiguration.java

java

深色版本

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableConfigurationProperties(SnowflakeProperties.class)
public class SnowflakeAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic SnowflakeIdGenerator snowflakeIdGenerator(SnowflakeProperties properties, MeterRegistry registry) {return new SnowflakeIdGenerator(properties, registry);}
}

✅ 8. META-INF/spring.factories

properties

深色版本

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.snowflake.SnowflakeAutoConfiguration

✅ 9. application.yml 配置示例

yaml

深色版本

server:port: 8080snowflake:datacenter-id: 1# worker-id: 5                    # 可指定registry-type: nacos             # 或 zookeeper / nonenacos-server-addr: localhost:8848zookeeper-connect-string: localhost:2181epoch: 1288834974657management:endpoints:web:exposure:include: health,info,prometheusmetrics:export:prometheus:enabled: true

✅ 10. Prometheus 监控指标(访问 /actuator/prometheus

text

深色版本

# HELP snowflake_ids_generated_total Total number of Snowflake IDs generated
# TYPE snowflake_ids_generated_total counter
snowflake_ids_generated_total 1234# HELP snowflake_clock_backward_events_total Number of clock backward events
# TYPE snowflake_clock_backward_events_total counter
snowflake_clock_backward_events_total 1

Prometheus 可采集这些指标,Grafana 可做可视化。


✅ 使用方式

  1. 启动项目
  2. 调用获取 ID:
    bash

    深色版本

    GET http://localhost:8080/api/id
    返回:
    json

    深色版本

    {"id": 1955540000123456789}
  3. 查看监控:
    bash

    深色版本

    GET http://localhost:8080/actuator/prometheus

✅ 总结:功能完整闭环

功能已实现
✅ Spring Boot 自动配置✔️
✅ 可配置 datacenter/worker✔️
✅ Nacos / ZooKeeper 动态分配 workerId✔️
✅ REST API 获取 ID✔️
✅ Prometheus 指标监控✔️
✅ 时钟回拨监控✔️
✅ 日志 + 健康检查✔️

🚀 下一步建议

  • ✅ 打成独立 starter(snowflake-spring-boot-starter
  • ✅ 支持 Redis 分布式锁分配 workerId
  • ✅ 增加 ID 解析工具(反解时间、datacenter、worker 等)
  • ✅ 集成 OpenTelemetry 追踪 ID 生成链路

如果你希望我:

  • 把这个项目打包成完整 GitHub 项目结构
  • 提供 Docker 部署脚本
  • 提供 Grafana 仪表盘 JSON
  • 支持多租户或命名空间

欢迎继续告诉我,我可以为你生成完整的企业级 ID 生成服务方案!🚀

http://www.lryc.cn/news/627027.html

相关文章:

  • 自动驾驶导航信号使用方式调研
  • C语言实现全排列(非递归法)(以猪八戒买包子的故事为例解释)
  • SpringBoot 整合 Langchain4j RAG 技术深度使用解析
  • imx6ull-驱动开发篇30——Linux 非阻塞IO实验
  • redis---常用数据类型及内部编码
  • 设计具有功能安全和网络安全能力的新型半导体芯片
  • 攻克PostgreSQL专家认证
  • Unicode 字符串转 UTF-8 编码算法剖析
  • JVM面试精选 20 题(终)
  • SQL count(*)与 sum 区别
  • 第三阶段数据-4:SqlHelper类,数据库删除,DataTable创建
  • STM32F4 内存管理介绍及应用
  • 建模工具Sparx EA的多视图协作教程
  • PyTorch - Developer Notes
  • 吴恩达 Machine Learning(Class 3)
  • 国产化PDF处理控件Spire.PDF教程:如何使用 Python 添加水印到 PDF
  • Linux命令大全-ps命令
  • Linux系统之部署nullboard任务管理工具
  • 基于springboot中学信息技术课程教学网站
  • 栈上创建和堆上创建区别
  • Nginx 的完整配置文件结构、配置语法以及模块详解
  • 设计模式1-单例模式
  • 继续记事本项目
  • 盲盒商城h5源码搭建可二开幸运盲盒回收转增定制开发教程
  • Hyperledger Fabric官方中文教程-改进笔记(十三)-使用测试网络创建通道
  • Google Chrome 扩展不受信任 - 不受支持的清单版本 解决方案
  • 整体设计 之定稿 “凝聚式中心点”原型 --整除:智能合约和DBMS的在表层挂接 能/所 依据的深层套接
  • AR 虚实叠加技术在工业设备运维中的实现流程方案
  • 云原生环境下的ITSM新趋势:从传统运维到智能化服务管理
  • MySQL 50 道经典练习题及答案