一、概述
雪花算法id是一個分布式可用的id生成器,也是現在廣泛應用的分布式情況下生成全局唯一id的解決方案之一,所以對雪花算法id的深入了解十分有必要。
二、原理
雪花算法id的原理是利用當前時間戳、工作機器id、序列號三個部分來生成全局唯一id。
1、時間戳
時間戳是雪花算法id生成的第一部分,一般為41位,能夠使用的時長最長約69年,當前時間戳減去一個固定的時間點比如“2020-01-01”後右移22位即可獲得一個41位的時間戳。
2、工作機器id
工作機器id是一個在分布式系統中必須唯一的標識,一般為10位,5位表示數據中心id,5位表示機器id,能夠使用的最多數據中心id數量是32個,每個數據中心內部最多機器數量是32個。
3、序列號
序列號是每個工作機器id內部單調遞增的計數器,一般為12位,最多可以生成4096個id。序列號溢出後需要等到下一個毫秒進行生成。
三、代碼實現
public class SnowflakeIdGenerator {
// 開始時間戳
private static final long BEGIN_TIMESTAMP = 1577808000000L;
// 數據中心id的位數
private static final long DATA_CENTER_ID_BITS = 5L;
// 機器id的位數
private static final long MACHINE_ID_BITS = 5L;
// 序列號的位數
private static final long SEQUENCE_BITS = 12L;
// 數據中心id最大值
private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
// 機器id最大值
private static final long MAX_MACHINE_ID = ~(-1L << MACHINE_ID_BITS);
// 序列號最大值
private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);
// 數據中心id左移位數(機器id內部共享此位)
private static final long DATA_CENTER_LEFT_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS;
// 機器id左移位數
private static final long MACHINE_LEFT_SHIFT = SEQUENCE_BITS;
// 時間戳左移位數
private static final long TIMESTAMP_LEFT_SHIFT = DATA_CENTER_LEFT_SHIFT + DATA_CENTER_ID_BITS;
// 數據中心id
private long dataCenterId;
// 機器id
private long machineId;
// 序列號
private long sequence;
// 最後生成id的時間戳
private long lastTimestamp = -1L;
/**
* 構造函數
* @param dataCenterId 數據中心id
* @param machineId 機器id
*/
public SnowflakeIdGenerator(long dataCenterId, long machineId) {
if (dataCenterId MAX_DATA_CENTER_ID) {
throw new IllegalArgumentException("data center id can't be greater than " + MAX_DATA_CENTER_ID + " or less than 0");
}
if (machineId MAX_MACHINE_ID) {
throw new IllegalArgumentException("machine id can't be greater than " + MAX_MACHINE_ID + " or less than 0");
}
this.dataCenterId = dataCenterId;
this.machineId = machineId;
}
/**
* 生成id方法
* @return id
*/
public synchronized long generateId() {
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 = waitUntilNextTime(lastTimestamp);
}
} else {
sequence = 0;
}
lastTimestamp = currentTimestamp;
return ((currentTimestamp - BEGIN_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT)
| (dataCenterId << DATA_CENTER_LEFT_SHIFT)
| (machineId << MACHINE_LEFT_SHIFT)
| sequence;
}
/**
* 等待下一毫秒
* @param lastTimestamp 最後生成id的時間戳
* @return 下一毫秒的時間戳
*/
private long waitUntilNextTime(long lastTimestamp) {
long time = System.currentTimeMillis();
while (time <= lastTimestamp) {
time = System.currentTimeMillis();
}
return time;
}
}
四、使用場景
雪花算法id適用於需要生成全局唯一id的場景,比如訂單號、用戶id等。在分布式場景下,也可以用於解決單個節點出現的並發問題。
五、總結
通過對雪花算法id的深入介紹,相信大家對它有了更深入的了解。在開發過程中,如果需要生成全局唯一id,可以考慮使用雪花算法id。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/239851.html
微信掃一掃
支付寶掃一掃