目錄
- 什麼是Snowflake算法?
- 為什麼選擇Snowflake?
- 詳細集成過程
- 1. 環境準備與依賴引入
- 2. 公共配置類:SnowflakeConfig
- 3. Nacos配置:多模塊YML統一
- 4. 實體類與數據庫適配
- 5. 業務層實現
- 集成中常見問題及解決方案
- 集成成功驗證
- 注意事項
什麼是Snowflake算法?
Snowflake是由Twitter(現X)開發的分佈式唯一ID生成算法,專為高併發微服務環境設計。它生成64位整數ID(Long類型),結構清晰:1位符號位(固定0)+41位時間戳(毫秒級,支持69年)+10位機器標識(5位數據中心ID + 5位Worker ID,支持1024節點)+12位序列號(每毫秒4096個ID)。無需中心化數據庫或鎖,通過本地時鐘+機器信息實現去中心化生成。核心優勢在於全局唯一(時間+空間隔離)、趨勢遞增(優化索引)、高吞吐(無IO瓶頸),已成為分佈式系統(如Kafka、MongoDB)標配。
為什麼選擇Snowflake?
微服務時代,Pig4Cloud如pig-oa、pig-upms等業務模塊獨立部署,高QPS下UUID散亂、Redis原子遞增網絡瓶頸凸顯。Snowflake(Twitter開源)以64位結構(時間戳+機器ID+序列)保證全局唯一、單調遞增、高吞吐,完美適配MyBatis-Plus的IdentifierGenerator。無外部依賴,本地生成,Pig4Cloud的Nacos配置中心更易統一。
詳細集成過程
1. 環境準備與依賴引入
- 項目架構:Pig4Cloud多模塊(pig-common-core共享工具,pig-oa-biz業務實現,pig-oa-api對外接口)。
- 添加Hutool:在根
pom.xml或pig-common-core/pom.xml:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.28</version>
</dependency>
- 運行
mvn clean install,確保版本>=5.7.0(Snowflake支持)。
2. 公共配置類:SnowflakeConfig
在pig-common-core/src/main/java/com/pig4cloud/pig/common/core/config/新建SnowflakeConfig.java:
package com.pig4cloud.pig.common.core.config;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Configuration
public class SnowflakeConfig {
private long workerId;
private long datacenterId = 1L;
private Snowflake snowflake;
@PostConstruct
public void init() {
try {
String hostAddress = InetAddress.getLocalHost().getHostAddress();
workerId = NetUtil.ipv4ToLong(hostAddress) % 32L;
System.out.println("Snowflake 初始化:workerId=" + workerId + ", datacenterId=" + datacenterId);
} catch (UnknownHostException e) {
workerId = 0L;
e.printStackTrace();
}
this.snowflake = IdUtil.getSnowflake(workerId, datacenterId);
}
@Bean
@Primary
public IdentifierGenerator snowflakeIdGenerator() {
return (Object entity) -> snowflake.nextId(); // 匹配MP接口
}
}
- 邏輯:IP轉workerId(0-31),@PostConstruct單例初始化。@Primary優先級,確保覆蓋默認生成器。
3. Nacos配置:多模塊YML統一
Pig4Cloud用Nacos管理DataId(如pig-umps-biz-dev.yml)。編輯每個業務模塊的YML(application-dev.yml作為fallback):
mybatis-plus:
global-config:
db-config:
id-type: ASSIGN_ID # 核心切換
logic-delete-field: delFlag # 統一邏輯刪除(String, 0/1)
logic-delete-value: 1
logic-not-delete-value: 0
# 其他原有配置...
- 批量操作:Nacos控制枱搜索DataId,替換mybatis-plus塊,發佈。繼承
spring.cloud.nacos.config.shared-configs拉取公共配置。 - Snowflake擴展:可選加
snowflake.datacenter-id: 1(模塊區分),用@Value注入。
4. 實體類與數據庫適配
- 實體:如
EmployeesEntity(pig-oa-biz/entity):
@Data
@TableName("employees")
public class EmployeesEntity extends Model<OaEmployeesEntity> {
@TableId(type = IdType.ASSIGN_ID) // 可選,優先全局
private Long id; // BIGINT對應
@TableLogic
@TableField(fill = FieldFill.INSERT)
private String delFlag; // 邏輯刪除
// 其他字段...
}
- 繼承Model自動CRUD,@TableField(fill)填充createTime等。
- 數據庫:主鍵
id BIGINT NOT NULL PRIMARY KEY,確保無默認值(MP自生成)。如MySQL:
ALTER TABLE oa_employees MODIFY id BIGINT NOT NULL COMMENT 'Snowflake ID';
5. 業務層實現
- Service(biz):
EmployeesServiceImpl extends ServiceImpl<...>:
@Transactional
public Boolean save(EmployeesEntity entity) {
entity.setDelFlag("0");
return this.save(entity); // ID自動填充
}
- API(api):Controller POST保存,Feign暴露。
集成中常見問題及解決方案
- 編譯報錯:Lambda“wrong number of parameters”——MP nextId(Object entity),改
(Object entity) -> snowflake.nextId()忽略entity。 - 方法未解析:
Cannot resolve 'nextId'——import cn.hutool.core.lang.Snowflake; 刷新Maven。 - ID未生成:fallback到auto——檢查@Primary Bean加載,日誌無“Snowflake 初始化”?加@ComponentScan掃描common-core。
- 邏輯刪除失效:字段不匹配——Nacos
logic-delete-field: delFlagvs 實體deleted,統一delFlag(Pig4Cloud標準)。 - 時鐘回撥:容器NTP不同步,ID重複——生產同步時間服務器,或用美團Leaf備選。
- 高併發碰撞:workerId重複——Docker環境IP不穩,用Nacos動態注入datacenterId。
集成成功驗證
重啓pig-umps-biz,日誌輸出初始化信息。Postman POST保存實體,響應ID為19位Long(e.g., 1786xxxxxxxxxxxxx)。JMeter 1000QPS循環保存,查表ID遞增無重複。Swagger測試CRUD,delFlag=1邏輯刪生效。跨模塊(如upms調用emp Feign)ID全局唯一。
注意事項
- 性能:本地生成>26k/s,監控序列溢出(12位,夠用)。
- 擴展:多環境datacenterId不同(dev=1, prod=10);容器用pod標籤注入workerId。
- 兼容:Long序列化JSON注意;數據庫索引優化趨勢ID。
- 回滾:YML id-type: auto,刪Bean。