69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
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
|
|
);
|
|
}
|
|
}
|