Java使用雪花算法生成唯一ID的實現(xiàn)示例
雪花算法(Snowflake ID)是 Twitter 開源的一種分布式 ID 生成算法,其目的是生成全局唯一的 ID。該算法的核心思想是將一個 64 位的二進制數(shù)字分成幾個部分,每個部分表示不同的信息,例如數(shù)據(jù)中心ID、機器ID、序列號等。這些部分的取值范圍可以根據(jù)實際情況進行調(diào)整。

使用雪花算法生成的 ID 具有以下特點:
- 全局唯一,ID 不會重復。
- 按時間有序,新生成的 ID 比舊的 ID 大。
- 可以在分布式環(huán)境下生成,不需要中心節(jié)點協(xié)調(diào)。
- 高性能,生成 ID 的速度快。
因其具有全局唯一和分布式特性,常被用于互聯(lián)網(wǎng)應(yīng)用的分布式系統(tǒng)中,如訂單號生成、數(shù)據(jù)庫主鍵生成等。
具體實現(xiàn)代碼如下:
public class Snowflake {
/** 開始時間戳 (2021-01-01) */
private final long START_TIMESTAMP = 1609430400000L;
/** 機器ID所占的位數(shù) */
private final long WORKER_ID_BITS = 5L;
/** 數(shù)據(jù)標識ID所占的位數(shù) */
private final long DATA_CENTER_ID_BITS = 5L;
/** 支持的最大機器ID,結(jié)果是31 (0B11111) */
private final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
/** 支持的最大數(shù)據(jù)標識ID,結(jié)果是31 (0B11111) */
private final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
/** 序列在ID中占的位數(shù) */
private final long SEQUENCE_BITS = 12L;
/** 機器ID向左移12位 */
private final long WORKER_ID_SHIFT = SEQUENCE_BITS;
/** 數(shù)據(jù)標識ID向左移17位(12+5) */
private final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
/** 時間戳向左移22位(5+5+12) */
private final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;
/** 支持的最大序列號,結(jié)果是4095 (0B111111111111) */
private final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);
/** 工作機器ID */
private final long workerId;
/** 數(shù)據(jù)中心ID */
private final long dataCenterId;
/** 毫秒內(nèi)序列號 */
private long sequence = 0L;
/** 上次生成ID的時間戳 */
private long lastTimestamp = -1L;
/**
* 構(gòu)造函數(shù)
* @param workerId 工作機器ID
* @param dataCenterId 數(shù)據(jù)中心ID
*/
public Snowflake(long workerId, long dataCenterId) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException(String.format("WorkerID不能超過%d且不能小于0", MAX_WORKER_ID));
}
if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
throw new IllegalArgumentException(String.format("DataCenterID不能超過%d且不能小于0", MAX_DATA_CENTER_ID));
}
this.workerId = workerId;
this.dataCenterId = dataCenterId;
}
/**
* 生成ID
* @return long類型的ID
*/
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
// 如果當前時間小于上次生成ID的時間戳,說明系統(tǒng)時鐘回退過,拋出異常
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("系統(tǒng)時鐘回退,拒絕生成ID,上次生成ID的時間戳:%d,當前時間戳:%d",
lastTimestamp, timestamp));
}
// 如果當前時間等于上次生成ID的時間戳(同一毫秒內(nèi)),則序列號加1
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
if (sequence == 0) {
// 如果序列號已經(jīng)超過最大值,需要等待到下一毫秒再繼續(xù)生成ID
timestamp = waitNextMillis(timestamp);
}
} else {
sequence = 0L;
}
// 更新上次生成ID的時間戳
lastTimestamp = timestamp;
// 生成ID
return ((timestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT) |
(dataCenterId << DATA_CENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
}
/**
* 等待下一毫秒
* @param timestamp 上次生成ID的時間戳
* @return 下一毫秒的時間戳
*/
private long waitNextMillis(long timestamp) {
long nextTimestamp = System.currentTimeMillis();
while (nextTimestamp <= timestamp) {
nextTimestamp = System.currentTimeMillis();
}
return nextTimestamp;
}
// 示例
public static void main(String[] args) {
Snowflake snowflake = new Snowflake(1, 1);
System.out.println(snowflake.nextId());
}
}
在上述代碼中,可以通過調(diào)整START_TIMESTAMP、WORKER_ID_BITS、DATA_CENTER_ID_BITS、SEQUENCE_BITS等參數(shù)來滿足不同的需求,例如支持更多的機器、更高的QPS等。
這是批量生成的ID:

到此這篇關(guān)于Java使用雪花算法生成唯一ID的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)Java 雪花算法生成唯一ID內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring gateway + Oauth2實現(xiàn)單點登錄及詳細配置
gateway是基于 WebFlux的響應(yīng)式編程框架,所以在使用securityConfig時采用的注解是@EnableWebFluxSecurity,接下來通過本文給大家介紹Spring gateway + Oauth2實現(xiàn)單點登錄及詳細配置,感興趣的朋友一起看看吧2021-09-09
rabbitmq的消息持久化處理開啟,再關(guān)閉后,消費者啟動報錯問題
這篇文章主要介紹了rabbitmq的消息持久化處理開啟,再關(guān)閉后,消費者啟動報錯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
Springboot+jwt實現(xiàn)在線用戶功能(示例代碼)
這篇文章主要介紹了Springboot+jwt實現(xiàn)在線用戶功能,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-12-12
Java批量向PDF文件中添加圖像水印實現(xiàn)細節(jié)
這篇文章主要為大家介紹了Java批量向PDF文件中添加圖像水印實現(xiàn)細節(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05

