init:first commit of plus-ui
This commit is contained in:
68
src/utils/snowflake.ts
Normal file
68
src/utils/snowflake.ts
Normal file
@ -0,0 +1,68 @@
|
||||
export class SnowflakeIdGenerator {
|
||||
private readonly startTimeStamp = 1609459200000; // 起始时间戳,这里设置为 2021-01-01 00:00:00
|
||||
private readonly workerIdBits = 5;
|
||||
private readonly dataCenterIdBits = 5;
|
||||
private readonly sequenceBits = 12;
|
||||
|
||||
private readonly maxWorkerId = -1 ^ (-1 << this.workerIdBits);
|
||||
private readonly maxDataCenterId = -1 ^ (-1 << this.dataCenterIdBits);
|
||||
|
||||
private readonly workerIdShift = this.sequenceBits;
|
||||
private readonly dataCenterIdShift = this.sequenceBits + this.workerIdBits;
|
||||
private readonly timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits;
|
||||
private readonly sequenceMask = -1 ^ (-1 << this.sequenceBits);
|
||||
|
||||
private workerId: number;
|
||||
private dataCenterId: number;
|
||||
private sequence = 0;
|
||||
private lastTimestamp = -1;
|
||||
|
||||
constructor(workerId: number, dataCenterId: number) {
|
||||
if (workerId > this.maxWorkerId || workerId < 0) {
|
||||
throw new Error(`Worker ID 必须在 0 到 ${this.maxWorkerId} 之间`);
|
||||
}
|
||||
if (dataCenterId > this.maxDataCenterId || dataCenterId < 0) {
|
||||
throw new Error(`数据中心 ID 必须在 0 到 ${this.maxDataCenterId} 之间`);
|
||||
}
|
||||
this.workerId = workerId;
|
||||
this.dataCenterId = dataCenterId;
|
||||
}
|
||||
|
||||
private waitNextMillis(lastTimestamp: number): number {
|
||||
let timestamp = this.getCurrentTimestamp();
|
||||
while (timestamp <= lastTimestamp) {
|
||||
timestamp = this.getCurrentTimestamp();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
private getCurrentTimestamp(): number {
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
nextId(): number {
|
||||
let timestamp = this.getCurrentTimestamp();
|
||||
|
||||
if (timestamp < this.lastTimestamp) {
|
||||
throw new Error('时钟回拨,拒绝生成 ID 达 ' + (this.lastTimestamp - timestamp) + ' 毫秒');
|
||||
}
|
||||
|
||||
if (timestamp === this.lastTimestamp) {
|
||||
this.sequence = (this.sequence + 1) & this.sequenceMask;
|
||||
if (this.sequence === 0) {
|
||||
timestamp = this.waitNextMillis(this.lastTimestamp);
|
||||
}
|
||||
} else {
|
||||
this.sequence = 0;
|
||||
}
|
||||
|
||||
this.lastTimestamp = timestamp;
|
||||
|
||||
return (
|
||||
((timestamp - this.startTimeStamp) << this.timestampLeftShift) |
|
||||
(this.dataCenterId << this.dataCenterIdShift) |
|
||||
(this.workerId << this.workerIdShift) |
|
||||
this.sequence
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user