You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

285 lines
14 KiB

1 month ago
# 雪花算法配置
<cite>
**本文档引用的文件**
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
- [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java)
- [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [application.yml](file://crm-app/src/main/resources/application.yml)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向分布式ID生成器的配置与使用,聚焦于雪花算法在工程中的落地实践。内容涵盖机器ID、数据中心ID、序列号等关键参数的配置方式与时钟回拨处理策略;同时提供自定义ID生成器实现、ID生成策略选择、ID格式规范说明,并给出高可用配置、性能优化与故障恢复方案,以及ID冲突检测与处理机制建议。
## 项目结构
本项目将雪花算法相关能力集中在基础模块中,通过配置类与ID生成器实现解耦业务代码,便于在不同环境(开发、测试、生产)灵活切换与扩展。
```mermaid
graph TB
A["应用启动<br/>application.yml"] --> B["MybatisPlus配置<br/>MybatisPlusConfig"]
B --> C["雪花属性注入<br/>SnowflakeProperties"]
C --> D["雪花ID生成器<br/>SnowflakeIdWorker"]
D --> E["自定义ID生成器适配<br/>CustomIdGenerator"]
E --> F["业务实体持久化<br/>MyBatis-Plus"]
```
图表来源
- [application.yml:1-200](file://crm-app/src/main/resources/application.yml#L1-L200)
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
- [SnowflakeProperties.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L200)
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
- [CustomIdGenerator.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java#L1-L200)
章节来源
- [application.yml:1-200](file://crm-app/src/main/resources/application.yml#L1-L200)
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
- [SnowflakeProperties.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L200)
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
- [CustomIdGenerator.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java#L1-L200)
## 核心组件
- SnowflakeProperties:集中管理雪花算法所需的环境参数,如数据中心ID、机器ID、时间戳位数、序列号位数等,支持从配置文件注入。
- SnowflakeIdWorker:雪花算法的核心实现,负责按位拼接时间戳、数据中心ID、机器ID与序列号,保证全局唯一且趋势递增。
- CustomIdGenerator:对MyBatis-Plus的ID生成策略进行适配,使业务实体在插入时自动使用雪花ID。
- MybatisPlusConfig:注册并装配ID生成器到MyBatis-Plus,完成从配置到生成的端到端链路。
章节来源
- [SnowflakeProperties.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L200)
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
- [CustomIdGenerator.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java#L1-L200)
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
## 架构总览
下图展示了从配置加载到ID生成的完整流程,包括时钟回拨检测与告警路径。
```mermaid
sequenceDiagram
participant App as "应用"
participant Props as "SnowflakeProperties"
participant Worker as "SnowflakeIdWorker"
participant Gen as "CustomIdGenerator"
participant MP as "MyBatis-Plus"
App->>Props : "读取雪花配置(数据中心ID/机器ID/位数)"
App->>MP : "初始化ID生成策略"
MP->>Gen : "注册自定义ID生成器"
Gen->>Worker : "调用nextId()"
Worker->>Worker : "获取当前时间戳"
Worker->>Worker : "校验是否发生时钟回拨"
alt "时钟回拨"
Worker-->>Gen : "抛出异常或降级策略"
Gen-->>App : "记录告警并返回错误码"
else "正常推进"
Worker->>Worker : "分配序列号并拼接ID"
Worker-->>Gen : "返回雪花ID"
Gen-->>MP : "返回ID供持久化"
MP-->>App : "持久化成功"
end
```
图表来源
- [SnowflakeProperties.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L200)
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
- [CustomIdGenerator.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java#L1-L200)
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
## 详细组件分析
### SnowflakeProperties 配置项
- 作用:集中管理雪花算法的参数,便于多环境差异化配置。
- 关键配置项(示例键名):
- 数据中心ID:标识不同机房或部署域,避免跨域ID冲突。
- 机器ID:标识同一数据中心内的具体节点,确保单机内唯一。
- 时间戳位数:决定时间部分占用的比特数,影响ID长度与时间跨度。
- 序列号位数:决定单毫秒内可生成的最大ID数量。
- 起始时间:用于计算相对时间戳,减少高位占用。
- 配置来源:通常来自 application.yml 或通过环境变量覆盖。
章节来源
- [SnowflakeProperties.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L200)
- [application.yml:1-200](file://crm-app/src/main/resources/application.yml#L1-L200)
### SnowflakeIdWorker 实现要点
- 职责:实现雪花算法核心逻辑,包括时间戳推进、序列号自增、时钟回拨检测与处理。
- 关键点:
- 时间戳:使用系统时钟,需保证单调递增;若检测到回拨,应触发告警与降级。
- 序列号:在同一毫秒内自增,达到上限后等待下一毫秒。
- ID拼接:按“时间戳 | 数据中心ID | 机器ID | 序列号”的位布局组合。
- 线程安全:内部状态需并发安全,避免竞争条件导致重复ID。
- 时钟回拨处理:
- 检测:比较当前时间与上次使用时间戳,若小于则判定为回拨。
- 策略:可选择等待回拨时间、快速失败并告警、或切换到备用生成器。
- 监控:记录回拨事件与持续时间,便于运维观测与定位。
章节来源
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
### CustomIdGenerator 适配层
- 作用:将雪花ID生成器接入MyBatis-Plus的ID生成策略,使实体插入时自动获得雪花ID。
- 集成点:
- 在MyBatis-Plus配置中注册自定义ID生成器。
- 指定实体主键字段使用自定义生成器。
- 优势:业务代码无需显式设置ID,降低耦合度与出错概率。
章节来源
- [CustomIdGenerator.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java#L1-L200)
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
### MybatisPlusConfig 装配
- 职责:统一装配MyBatis-Plus相关组件,包括分页、元数据填充、ID生成器等。
- 装配顺序:
- 加载SnowflakeProperties配置。
- 创建SnowflakeIdWorker实例。
- 注册CustomIdGenerator作为默认ID生成策略。
- 扩展性:可通过条件装配或Profile切换不同生成策略。
章节来源
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
### 类关系图
```mermaid
classDiagram
class SnowflakeProperties {
+long datacenterId
+long workerId
+int timestampBits
+int sequenceBits
+long startTime
+get() ...
}
class SnowflakeIdWorker {
+long nextId() long
-checkClockBackward() void
-incrementSequence() long
-waitNextMillis() void
}
class CustomIdGenerator {
+generate(entity) Object
-delegateTo(worker) Object
}
class MybatisPlusConfig {
+registerIdGenerator() void
-loadProperties() SnowflakeProperties
}
MybatisPlusConfig --> SnowflakeProperties : "读取配置"
MybatisPlusConfig --> CustomIdGenerator : "注册生成器"
CustomIdGenerator --> SnowflakeIdWorker : "调用生成ID"
SnowflakeIdWorker --> SnowflakeProperties : "使用配置参数"
```
图表来源
- [SnowflakeProperties.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L200)
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
- [CustomIdGenerator.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java#L1-L200)
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
### 时钟回拨处理流程图
```mermaid
flowchart TD
Start(["进入 nextId"]) --> GetTime["获取当前系统时间戳"]
GetTime --> Compare{"是否小于上次时间戳?"}
Compare --> |是| ClockBack["触发时钟回拨处理"]
ClockBack --> Strategy{"选择处理策略"}
Strategy --> |等待| Wait["等待至下次毫秒"]
Strategy --> |告警| Alert["记录告警并返回错误"]
Strategy --> |降级| Fallback["切换到备用生成器"]
Compare --> |否| IncSeq["序列号自增"]
IncSeq --> WrapCheck{"是否溢出?"}
WrapCheck --> |是| WaitNext["等待下一毫秒"]
WrapCheck --> |否| BuildId["拼接ID并返回"]
Wait --> GetTime
Alert --> End(["结束"])
Fallback --> End
BuildId --> End
```
图表来源
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
## 依赖关系分析
- 配置依赖:SnowflakeProperties从application.yml读取参数,支持多环境覆盖。
- 装配依赖:MybatisPlusConfig装配CustomIdGenerator,使其成为MyBatis-Plus的默认ID生成器。
- 运行时依赖:CustomIdGenerator委托SnowflakeIdWorker执行实际ID生成逻辑。
- 外部依赖:无强外部依赖,仅依赖JDK与MyBatis-Plus框架。
```mermaid
graph LR
YML["application.yml"] --> Props["SnowflakeProperties"]
Props --> Config["MybatisPlusConfig"]
Config --> Gen["CustomIdGenerator"]
Gen --> Worker["SnowflakeIdWorker"]
```
图表来源
- [application.yml:1-200](file://crm-app/src/main/resources/application.yml#L1-L200)
- [SnowflakeProperties.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L200)
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
- [CustomIdGenerator.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java#L1-L200)
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
章节来源
- [application.yml:1-200](file://crm-app/src/main/resources/application.yml#L1-L200)
- [SnowflakeProperties.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L200)
- [MybatisPlusConfig.java:1-200](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L200)
- [CustomIdGenerator.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java#L1-L200)
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
## 性能考虑
- 时间戳精度:合理设置时间戳位数,平衡ID长度与时间跨度。
- 序列号范围:根据单机QPS估算序列号位数,避免频繁等待下一毫秒。
- 并发安全:内部使用原子操作或锁机制保证线程安全,减少锁粒度。
- 内存占用:避免在高频路径上创建临时对象,复用缓冲与状态。
- I/O无关:ID生成不依赖网络或磁盘,确保低延迟。
[本节为通用性能指导,不直接分析具体文件]
## 故障排查指南
- 时钟回拨告警:
- 现象:ID生成失败或抛出异常,日志中出现回拨提示。
- 排查:检查服务器时钟同步服务(NTP),确认是否存在跳变。
- 处置:启用等待或降级策略,恢复后继续生成。
- ID重复:
- 现象:数据库唯一约束冲突。
- 排查:检查机器ID与数据中心ID是否重复,确认序列号未重置。
- 处置:重新分配唯一标识,必要时引入去重表或缓存校验。
- 性能抖动:
- 现象:ID生成耗时增加。
- 排查:检查CPU占用、锁竞争、GC停顿。
- 处置:优化锁粒度、调整JVM参数、扩容节点。
章节来源
- [SnowflakeIdWorker.java:1-200](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java#L1-L200)
- [application.yml:1-200](file://crm-app/src/main/resources/application.yml#L1-L200)
## 结论
通过将雪花算法封装为独立组件并与MyBatis-Plus无缝集成,项目在保持高性能与高可用的同时,提供了灵活的配置与扩展能力。合理的时钟回拨处理与监控告警机制,进一步增强了系统的稳定性与可维护性。
[本节为总结性内容,不直接分析具体文件]
## 附录
- ID格式规范建议:
- 位布局:时间戳 | 数据中心ID | 机器ID | 序列号
- 长度:通常为64位长整型,便于存储与传输
- 排序:时间优先,保证趋势递增
- 高可用配置建议:
- 多数据中心部署,隔离机器ID与数据中心ID
- 健康检查与自动切换备用生成器
- 监控指标:生成耗时、回拨次数、失败率
- 冲突检测与处理:
- 入库前唯一性校验(可选)
- 重试与幂等设计
- 审计日志与追溯
[本节为补充信息,不直接分析具体文件]