Files
td_official/src/utils/snowflake.ts
2025-05-21 11:24:53 +08:00

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
);
}
}