轉載自:https://www.tqwba.com/x_d/jishu/237497.html
如果在面試中被問及分布式唯一辨別,卻沒有答道雪花算法,那麼就有點說不過去了.
關于分布式唯一辨別中的雪花算法,網絡上的介紹很多,它隻是一個算法,可以用Python,Java等不同的語言實作它.即便是同一個語言,它的實作也有不同.

美團(Leaf)
百度(uid-generator)
這兩個也是業界比較知名的實作雪花算法的工具.
然而還有一個工具類,它就是
hutool工具中的雪花算法
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.2</version>
</dependency>
在它的内部也實作和提供了雪花算法,在這裡,我們就拿它作為講解雪花算法的案例.
cn.hutool.core.lang.Snowflake
最核心的方法就是下面這個
public synchronized long nextId() {
// 擷取目前時間戳
long timestamp = genTime();
// lastTimestamp表示你的程式在最後一次擷取分布式唯一辨別的時間戳(ms)
// 一台機器正常情況下,timestamp 是要大于 lastTimestamp的.如果timestamp < lastTimestamp表明伺服器的時間有問題,存在時鐘後退.
if (timestamp < lastTimestamp) {
// 容忍2秒内的時鐘後退
if(lastTimestamp - timestamp < 2000){
timestamp = lastTimestamp;
} else{
// 如果伺服器時間有問題(時鐘後退) 報錯。
throw new IllegalStateException(StrUtil.format("Clock moved backwards. Refusing to generate id for {}ms", lastTimestamp - timestamp));
}
}
if (timestamp == lastTimestamp) {
// 相同毫秒内,序列号自增
sequence = (sequence + 1) & sequenceMask;
// 同一毫秒的序列數已經達到最大
if (sequence == 0) {
// 循環等待下一個時間
timestamp = tilNextMillis(lastTimestamp);
}
} else {// timestamp > lastTimestamp
// 不同毫秒内, 序列号置為0
sequence = 0L;
}
lastTimestamp = timestamp;
// 通過按位或将各個部分拼接起來
return ((timestamp - twepoch) << timestampLeftShift) // 時間戳部分
| (dataCenterId << dataCenterIdShift) // 資料中心部分
| (workerId << workerIdShift) // 機器辨別部分
| sequence; // 序列号部分
}