/** * @file 雪花ID生成器 * @author AI助手 * @date 2024-12-30 * @lastEditor AI助手 * @lastEditTime 2024-12-30 * @description 基于Twitter雪花算法的分布式ID生成器,支持自定义workerId和datacenterId */ /** * 雪花ID生成器配置接口 * @property {number} workerId - 工作机器ID (0-31) * @property {number} datacenterId - 数据中心ID (0-31) * @property {number} sequence - 序列号起始值 * @property {number} epoch - 起始时间戳 (毫秒) */ export interface SnowflakeConfig { /** 工作机器ID,范围0-31 */ workerId: number; /** 数据中心ID,范围0-31 */ datacenterId: number; /** 序列号起始值,默认0 */ sequence?: number; /** 起始时间戳,默认2020-01-01 00:00:00 UTC */ epoch?: number; } /** * 雪花ID生成器类 * 生成64位长整型ID,格式:时间戳(41位) + 数据中心ID(5位) + 工作机器ID(5位) + 序列号(12位) */ export class Snowflake { /** 工作机器ID位数 */ private static readonly WORKER_ID_BITS = 5; /** 数据中心ID位数 */ private static readonly DATACENTER_ID_BITS = 5; /** 序列号位数 */ private static readonly SEQUENCE_BITS = 12; /** 最大工作机器ID */ private static readonly MAX_WORKER_ID = (1 << Snowflake.WORKER_ID_BITS) - 1; /** 最大数据中心ID */ private static readonly MAX_DATACENTER_ID = (1 << Snowflake.DATACENTER_ID_BITS) - 1; /** 最大序列号 */ private static readonly MAX_SEQUENCE = (1 << Snowflake.SEQUENCE_BITS) - 1; /** 工作机器ID左移位数 */ private static readonly WORKER_ID_SHIFT = Snowflake.SEQUENCE_BITS; /** 数据中心ID左移位数 */ private static readonly DATACENTER_ID_SHIFT = Snowflake.SEQUENCE_BITS + Snowflake.WORKER_ID_BITS; /** 时间戳左移位数 */ private static readonly TIMESTAMP_LEFT_SHIFT = Snowflake.SEQUENCE_BITS + Snowflake.WORKER_ID_BITS + Snowflake.DATACENTER_ID_BITS; /** 工作机器ID */ private readonly workerId: number; /** 数据中心ID */ private readonly datacenterId: number; /** 起始时间戳 */ private readonly epoch: number; /** 当前序列号 */ private sequence: number; /** 上次生成ID的时间戳 */ private lastTimestamp: number; /** * 构造函数 * @param config 雪花ID配置 * @throws {Error} 当workerId或datacenterId超出范围时抛出错误 */ constructor(config: SnowflakeConfig) { // 验证workerId范围 if (config.workerId < 0 || config.workerId > Snowflake.MAX_WORKER_ID) { throw new Error(`Worker ID must be between 0 and ${Snowflake.MAX_WORKER_ID}`); } // 验证datacenterId范围 if (config.datacenterId < 0 || config.datacenterId > Snowflake.MAX_DATACENTER_ID) { throw new Error(`Datacenter ID must be between 0 and ${Snowflake.MAX_DATACENTER_ID}`); } this.workerId = config.workerId; this.datacenterId = config.datacenterId; this.sequence = config.sequence || 0; this.epoch = config.epoch || 1577836800000; // 2020-01-01 00:00:00 UTC this.lastTimestamp = -1; } /** * 生成下一个雪花ID * @returns {bigint} 64位雪花ID * @throws {Error} 当系统时钟回拨时抛出错误 */ public nextId(): bigint { let timestamp = this.getCurrentTimestamp(); // 检查时钟回拨 if (timestamp < this.lastTimestamp) { const timeDiff = this.lastTimestamp - timestamp; throw new Error(`Clock moved backwards. Refusing to generate id for ${timeDiff} milliseconds`); } // 如果是同一毫秒内,递增序列号 if (timestamp === this.lastTimestamp) { this.sequence = (this.sequence + 1) & Snowflake.MAX_SEQUENCE; // 如果序列号溢出,等待下一毫秒 if (this.sequence === 0) { timestamp = this.waitNextMillis(this.lastTimestamp); } } else { // 不同毫秒,重置序列号 this.sequence = 0; } this.lastTimestamp = timestamp; // 生成雪花ID const id = ((BigInt(timestamp - this.epoch) << BigInt(Snowflake.TIMESTAMP_LEFT_SHIFT)) | (BigInt(this.datacenterId) << BigInt(Snowflake.DATACENTER_ID_SHIFT)) | (BigInt(this.workerId) << BigInt(Snowflake.WORKER_ID_SHIFT)) | BigInt(this.sequence)); return id; } /** * 解析雪花ID,返回各个组成部分 * @param id 雪花ID * @returns {object} 解析结果 */ public static parseId(id: bigint): { timestamp: number; datacenterId: number; workerId: number; sequence: number; createdAt: Date; } { const timestamp = Number((id >> BigInt(Snowflake.TIMESTAMP_LEFT_SHIFT)) & BigInt((1 << 41) - 1)); const datacenterId = Number((id >> BigInt(Snowflake.DATACENTER_ID_SHIFT)) & BigInt(Snowflake.MAX_DATACENTER_ID)); const workerId = Number((id >> BigInt(Snowflake.WORKER_ID_SHIFT)) & BigInt(Snowflake.MAX_WORKER_ID)); const sequence = Number(id & BigInt(Snowflake.MAX_SEQUENCE)); // 计算创建时间(使用默认epoch) const epoch = 1577836800000; // 2020-01-01 00:00:00 UTC const createdAt = new Date(epoch + timestamp); return { timestamp, datacenterId, workerId, sequence, createdAt, }; } /** * 获取当前时间戳(毫秒) * @returns {number} 当前时间戳 */ private getCurrentTimestamp(): number { return Date.now(); } /** * 等待下一毫秒 * @param lastTimestamp 上次时间戳 * @returns {number} 新的时间戳 */ private waitNextMillis(lastTimestamp: number): number { let timestamp = this.getCurrentTimestamp(); while (timestamp <= lastTimestamp) { timestamp = this.getCurrentTimestamp(); } return timestamp; } /** * 获取配置信息 * @returns {object} 当前配置 */ public getConfig(): { workerId: number; datacenterId: number; sequence: number; epoch: number; lastTimestamp: number; } { return { workerId: this.workerId, datacenterId: this.datacenterId, sequence: this.sequence, epoch: this.epoch, lastTimestamp: this.lastTimestamp, }; } } /** * 雪花ID生成器单例实例 * 使用默认配置:workerId=1, datacenterId=1 */ let snowflakeInstance: Snowflake | null = null; /** * 获取雪花ID生成器单例实例 * @param config 可选配置,如果不提供则使用默认配置 * @returns {Snowflake} 雪花ID生成器实例 */ export function getSnowflake(config?: Partial): Snowflake { if (!snowflakeInstance) { const defaultConfig: SnowflakeConfig = { workerId: 1, datacenterId: 1, ...config, }; snowflakeInstance = new Snowflake(defaultConfig); } return snowflakeInstance; } /** * 生成下一个雪花ID(便捷方法) * @returns {bigint} 64位雪花ID */ export function nextId(): bigint { return getSnowflake().nextId(); } /** * 解析雪花ID(便捷方法) * @param id 雪花ID * @returns {object} 解析结果 */ export function parseId(id: bigint) { return Snowflake.parseId(id); } /** * 创建自定义配置的雪花ID生成器 * @param config 雪花ID配置 * @returns {Snowflake} 新的雪花ID生成器实例 */ export function createSnowflake(config: SnowflakeConfig): Snowflake { return new Snowflake(config); }