🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@cdlab996/genid

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cdlab996/genid - npm Package Compare versions

Comparing version
1.2.1
to
1.3.0
+85
-237
dist/index.cjs

@@ -1,29 +0,54 @@

Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
//#region src/types/index.ts
/**
* ID 生成算法类型
*/
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/types.ts
/** ID 生成算法类型 */
let GenidMethod = /* @__PURE__ */ function(GenidMethod) {
/** 漂移算法(推荐用于高性能场景) */
/** 漂移算法(推荐,高并发下可突破每毫秒序列号上限) */
GenidMethod[GenidMethod["DRIFT"] = 1] = "DRIFT";
/** 传统算法 */
/** 传统算法(序列号耗尽时等待下一毫秒) */
GenidMethod[GenidMethod["TRADITIONAL"] = 2] = "TRADITIONAL";
return GenidMethod;
}({});
//#endregion
//#region src/index.ts
//#region src/config.ts
/** 将用户配置与默认值合并,返回完整内部配置 */
function initConfig(options) {
const config = {
workerId: options.workerId,
method: options.method === GenidMethod.TRADITIONAL ? GenidMethod.TRADITIONAL : GenidMethod.DRIFT,
baseTime: options.baseTime && options.baseTime > 0 ? options.baseTime : (/* @__PURE__ */ new Date("2020-01-01")).valueOf(),
workerIdBitLength: options.workerIdBitLength && options.workerIdBitLength > 0 ? options.workerIdBitLength : 6,
seqBitLength: options.seqBitLength && options.seqBitLength > 0 ? options.seqBitLength : 6,
maxSeqNumber: 0,
minSeqNumber: 0,
topOverCostCount: 0
};
config.maxSeqNumber = options.maxSeqNumber && options.maxSeqNumber > 0 ? options.maxSeqNumber : (1 << config.seqBitLength) - 1;
config.minSeqNumber = options.minSeqNumber && options.minSeqNumber > 0 ? options.minSeqNumber : 5;
config.topOverCostCount = options.topOverCostCount && options.topOverCostCount > 0 ? options.topOverCostCount : 2e3;
return config;
}
/** 校验配置合法性,不合法则抛出 Error */
function validateConfig(config) {
const { workerId, baseTime, workerIdBitLength, seqBitLength, minSeqNumber, maxSeqNumber } = config;
if (baseTime > Date.now()) throw new Error("[GenidOptimized] baseTime 不能大于当前时间");
if (workerIdBitLength < 1 || workerIdBitLength > 15) throw new Error("[GenidOptimized] workerIdBitLength 必须在 1 到 15 之间");
if (seqBitLength < 3 || seqBitLength > 21) throw new Error("[GenidOptimized] seqBitLength 必须在 3 到 21 之间");
if (workerIdBitLength + seqBitLength > 22) throw new Error("[GenidOptimized] workerIdBitLength + seqBitLength 不能超过 22");
const maxWorkerId = (1 << workerIdBitLength) - 1;
if (workerId < 0 || workerId > maxWorkerId) throw new Error(`[GenidOptimized] workerId 必须在 0 到 ${maxWorkerId} 之间`);
if (minSeqNumber < 5) throw new Error("[GenidOptimized] minSeqNumber 必须至少为 5(0-4 保留)");
if (maxSeqNumber < minSeqNumber) throw new Error("[GenidOptimized] maxSeqNumber 必须大于或等于 minSeqNumber");
}
//#endregion
//#region src/genid.ts
/**
* 优化版 Snowflake ID 生成器
* 基于 Snowflake 算法的分布式唯一 ID 生成器
*
* 基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理。
* - 漂移算法:高并发下借用未来时间戳,突破每毫秒序列号上限
* - 时钟回拨:使用保留序列号(0-4)优雅降级,不阻塞生成
* - 非线程安全,每个 Worker/进程应使用独立实例和不同 workerId
*
* 特性:
* - 漂移算法:提升高并发下的性能
* - 优雅处理时钟回拨,不阻塞生成
* - 可配置的位长度,灵活性高
* - 支持传统和漂移两种生成方法
*
* ⚠️ 注意:此实例不是线程安全的,每个 Worker/进程应该创建独立的实例并使用不同的 workerId
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
*/

@@ -47,25 +72,6 @@ var GenidOptimized = class {

_stats;
/**
* 构造函数,初始化 ID 生成器
*
* @param {Object} options - 配置选项
* @param {number} options.workerId - 工作节点/机器 ID(必须,范围 0 到 2^workerIdBitLength-1)
* @param {GenidMethod} [options.method=GenidMethod.DRIFT] - 算法类型
* @param {number} [options.baseTime=1577836800000] - 起始时间戳(毫秒,默认:2020-01-01)
* @param {number} [options.workerIdBitLength=6] - 工作节点 ID 的位数(1-15,默认:6)
* @param {number} [options.seqBitLength=6] - 序列号的位数(3-21,默认:6)
* @param {number} [options.maxSeqNumber] - 最大序列号(默认:2^seqBitLength-1)
* @param {number} [options.minSeqNumber=5] - 最小序列号(默认:5,0-4 保留)
* @param {number} [options.topOverCostCount=2000] - 最大漂移次数(默认:2000)
*
* @throws {Error} 如果缺少 workerId 或配置无效
*
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
*/
constructor(options) {
if (options.workerId === void 0 || options.workerId === null) throw new Error("[GenidOptimized] workerId 是必须参数");
const config = this._initConfig(options);
this._validateConfig(config);
const config = initConfig(options);
validateConfig(config);
this._initVariables(config);

@@ -79,45 +85,2 @@ this._stats = {

}
/**
* 初始化配置,设置默认值
* @private
* @param {Object} options - 用户提供的配置
* @returns {Object} 合并后的配置对象
*/
_initConfig(options) {
const config = {
workerId: options.workerId,
method: options.method === GenidMethod.TRADITIONAL ? GenidMethod.TRADITIONAL : GenidMethod.DRIFT,
baseTime: options.baseTime && options.baseTime > 0 ? options.baseTime : (/* @__PURE__ */ new Date("2020-01-01")).valueOf(),
workerIdBitLength: options.workerIdBitLength && options.workerIdBitLength > 0 ? options.workerIdBitLength : 6,
seqBitLength: options.seqBitLength && options.seqBitLength > 0 ? options.seqBitLength : 6,
maxSeqNumber: 0,
minSeqNumber: 0,
topOverCostCount: 0
};
config.maxSeqNumber = options.maxSeqNumber && options.maxSeqNumber > 0 ? options.maxSeqNumber : (1 << config.seqBitLength) - 1;
config.minSeqNumber = options.minSeqNumber && options.minSeqNumber > 0 ? options.minSeqNumber : 5;
config.topOverCostCount = options.topOverCostCount && options.topOverCostCount > 0 ? options.topOverCostCount : 2e3;
return config;
}
/**
* 验证配置参数的有效性
* @private
* @param {Object} config - 配置对象
* @throws {Error} 如果配置无效
*/
_validateConfig(config) {
const { workerId, workerIdBitLength, seqBitLength, minSeqNumber, maxSeqNumber } = config;
if (workerIdBitLength < 1 || workerIdBitLength > 15) throw new Error("[GenidOptimized] workerIdBitLength 必须在 1 到 15 之间");
if (seqBitLength < 3 || seqBitLength > 21) throw new Error("[GenidOptimized] seqBitLength 必须在 3 到 21 之间");
if (workerIdBitLength + seqBitLength > 22) throw new Error("[GenidOptimized] workerIdBitLength + seqBitLength 不能超过 22");
const maxWorkerId = (1 << workerIdBitLength) - 1;
if (workerId < 0 || workerId > maxWorkerId) throw new Error(`[GenidOptimized] workerId 必须在 0 到 ${maxWorkerId} 之间`);
if (minSeqNumber < 5) throw new Error("[GenidOptimized] minSeqNumber 必须至少为 5(0-4 保留)");
if (maxSeqNumber < minSeqNumber) throw new Error("[GenidOptimized] maxSeqNumber 必须大于或等于 minSeqNumber");
}
/**
* 初始化实例变量
* @private
* @param {Object} config - 配置对象
*/
_initVariables(config) {

@@ -140,15 +103,7 @@ this.method = BigInt(config.method);

}
/**
* 获取当前时间戳(相对于 baseTime 的毫秒数)
* @private
* @returns {bigint} 当前时间戳
*/
/** 获取相对于 baseTime 的当前时间戳 */
_getCurrentTimeTick() {
return BigInt(Date.now()) - this.baseTime;
}
/**
* 等待下一毫秒
* @private
* @returns {bigint} 下一毫秒时间戳
*/
/** 自旋等待直到时间前进到下一毫秒 */
_getNextTimeTick() {

@@ -160,8 +115,3 @@ let timeTick = this._getCurrentTimeTick();

spinCount++;
if (spinCount > maxSpinCount)
/**
* 如果自旋太多次,强制返回当前时间 + 1
* 这种情况理论上不应该发生,除非系统时间出现严重问题
*/
return this._lastTimeTick + 1n;
if (spinCount > maxSpinCount) return this._lastTimeTick + 1n;
timeTick = this._getCurrentTimeTick();

@@ -171,8 +121,3 @@ }

}
/**
* 根据组件计算 ID
* @private
* @param {bigint} useTimeTick - 使用的时间戳
* @returns {bigint} 计算得到的 ID
*/
/** 组装 ID:timestamp | workerId | sequence,并自增序列号 */
_calcId(useTimeTick) {

@@ -184,8 +129,3 @@ const result = (BigInt(useTimeTick) << this._timestampShift) + (this.workerId << this.seqBitLength) + this._currentSeqNumber;

}
/**
* 计算时钟回拨时的 ID
* @private
* @param {bigint} useTimeTick - 使用的时间戳
* @returns {bigint} 计算得到的 ID
*/
/** 时钟回拨时组装 ID,使用保留序列号(0-4)避免冲突 */
_calcTurnBackId(useTimeTick) {

@@ -197,7 +137,3 @@ const result = (BigInt(useTimeTick) << this._timestampShift) + (this.workerId << this.seqBitLength) + BigInt(this._turnBackIndex);

}
/**
* 处理漂移情况(漂移算法)
* @private
* @returns {bigint} 生成的 ID
*/
/** 漂移状态下生成 ID */
_nextOverCostId() {

@@ -238,7 +174,3 @@ const currentTimeTick = this._getCurrentTimeTick();

}
/**
* 正常生成 ID
* @private
* @returns {bigint} 生成的 ID
*/
/** 正常状态下生成 ID */
_nextNormalId() {

@@ -260,2 +192,9 @@ const currentTimeTick = this._getCurrentTimeTick();

}
if (this._turnBackTimeTick >= this._lastTimeTick) {
this._turnBackTimeTick = 0n;
this._turnBackIndex = 0;
this._lastTimeTick = this._getNextTimeTick();
this._currentSeqNumber = this.minSeqNumber;
return this._calcId(this._lastTimeTick);
}
return this._calcTurnBackId(this._turnBackTimeTick);

@@ -274,2 +213,7 @@ }

if (this._currentSeqNumber > this.maxSeqNumber) {
if (this.method === BigInt(GenidMethod.TRADITIONAL)) {
this._lastTimeTick = this._getNextTimeTick();
this._currentSeqNumber = this.minSeqNumber;
return this._calcId(this._lastTimeTick);
}
this._beginOverCostAction(currentTimeTick);

@@ -285,36 +229,10 @@ this._lastTimeTick++;

}
_beginOverCostAction(_useTimeTick) {}
_endOverCostAction(_useTimeTick) {}
_beginTurnBackAction(_useTimeTick) {}
_endTurnBackAction(_useTimeTick) {}
/**
* 钩子函数:开始漂移操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
* 生成 ID,返回 number。超出安全整数范围时抛错。
* @throws 当 ID >= Number.MAX_SAFE_INTEGER + 1 时
*/
_beginOverCostAction(useTimeTick) {}
/**
* 钩子函数:结束漂移操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
_endOverCostAction(useTimeTick) {}
/**
* 钩子函数:开始时钟回拨操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
_beginTurnBackAction(useTimeTick) {}
/**
* 钩子函数:结束时钟回拨操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
_endTurnBackAction(useTimeTick) {}
/**
* 生成下一个 ID
*
* @returns {number} 唯一 ID(Number 类型)
* @throws {Error} 如果 ID 超出 JavaScript 安全整数范围
*
* @example
* const id = genid.nextNumber();
* console.log(id); // 123456789012345
*/
nextNumber() {

@@ -325,13 +243,3 @@ const id = this._isOverCost ? this._nextOverCostId() : this._nextNormalId();

}
/**
* 生成下一个 ID
*
* 如果 ID 在安全范围内返回 Number,否则返回 BigInt
*
* @returns {number|bigint} 唯一 ID
*
* @example
* const id = genid.nextId();
* console.log(typeof id); // 'number' 或 'bigint'
*/
/** 生成 ID,安全范围内返回 number,否则返回 bigint */
nextId() {

@@ -341,25 +249,7 @@ const id = this._isOverCost ? this._nextOverCostId() : this._nextNormalId();

}
/**
* 生成下一个 ID
*
* @returns {bigint} 唯一 ID(BigInt 类型)
*
* @example
* const id = genid.nextBigId();
* console.log(id); // 123456789012345678n
*/
/** 生成 ID,始终返回 bigint */
nextBigId() {
return this._isOverCost ? this._nextOverCostId() : this._nextNormalId();
}
/**
* 批量生成 ID
*
* @param {number} count - 要生成的 ID 数量
* @param {boolean} [asBigInt=false] - 是否返回 BigInt 数组
* @returns {Array<number|bigint>} 唯一 ID 数组
*
* @example
* const ids = genid.nextBatch(100);
* const bigIds = genid.nextBatch(100, true);
*/
/** 批量生成 ID */
nextBatch(count, asBigInt = false) {

@@ -372,20 +262,7 @@ if (count <= 0) throw new Error("[GenidOptimized] 批量生成数量必须大于 0");

/**
* 解析 ID,提取其组成部分
* 解析 ID,提取时间戳、workerId、序列号
*
* @param {number|bigint|string} id - 要解析的 ID
* @returns {Object} 解析结果
* @returns {Date} return.timestamp - 生成时间戳
* @returns {number} return.timestampMs - 时间戳(毫秒)
* @returns {number} return.workerId - 工作节点 ID
* @returns {number} return.sequence - 序列号
*
* @example
* const info = genid.parse(id);
* console.log(info);
* // {
* // timestamp: Date,
* // timestampMs: 1609459200000,
* // workerId: 1,
* // sequence: 42
* // }
* genid.parse(id)
* // { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
*/

@@ -406,11 +283,3 @@ parse(id) {

}
/**
* 获取生成器统计信息
*
* @returns {Object} 统计数据
*
* @example
* const stats = genid.getStats();
* console.log(stats);
*/
/** 获取运行统计信息 */
getStats() {

@@ -428,5 +297,3 @@ const uptime = Date.now() - this._stats.startTime;

}
/**
* 重置统计数据
*/
/** 重置统计数据 */
resetStats() {

@@ -440,7 +307,3 @@ this._stats = {

}
/**
* 获取配置信息
*
* @returns {Object} 配置详情
*/
/** 获取当前配置信息 */
getConfig() {

@@ -464,14 +327,4 @@ const maxWorkerId = (1 << Number(this.workerIdBitLength)) - 1;

/**
* 验证 ID 是否为有效的 Snowflake ID
*
* @param {number|bigint|string} id - 要验证的 ID
* @param {boolean} [strictWorkerId=false] - 是否严格验证 workerId 必须匹配当前实例
* @returns {boolean} ID 是否有效
*
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
* genid.isValid(id); // true
* genid.isValid(12345); // false
* genid.isValid(id, true); // true (workerId 匹配)
* 验证 ID 是否为当前配置下合法的 Snowflake ID
* @param strictWorkerId - 为 true 时要求 workerId 匹配当前实例
*/

@@ -499,8 +352,3 @@ isValid(id, strictWorkerId = false) {

}
/**
* 将 ID 格式化为二进制字符串以便调试
*
* @param {number|bigint|string} id - 要格式化的 ID
* @returns {string} 格式化的二进制表示
*/
/** 将 ID 格式化为带标注的二进制字符串(调试用) */
formatBinary(id) {

@@ -523,4 +371,4 @@ const idBigInt = BigInt(id);

};
//#endregion
exports.GenidOptimized = GenidOptimized;
exports.GenidMethod = GenidMethod;
exports.GenidOptimized = GenidOptimized;

@@ -1,39 +0,51 @@

//#region src/types/index.d.ts
/**
* ID 生成算法类型
*/
//#region src/types.d.ts
/** ID 生成算法类型 */
declare enum GenidMethod {
/** 漂移算法(推荐用于高性能场景) */
/** 漂移算法(推荐,高并发下可突破每毫秒序列号上限) */
DRIFT = 1,
/** 传统算法 */
/** 传统算法(序列号耗尽时等待下一毫秒) */
TRADITIONAL = 2
}
/**
* ID 生成器配置选项
*/
/** ID 生成器构造选项 */
interface GenidOptions {
/** 工作节点/机器 ID(必须,范围 0 到 2^workerIdBitLength-1) */
/** 工作节点 ID(必须,范围 0 到 2^workerIdBitLength-1) */
workerId: number;
/** 算法类型(默认:GenidMethod.DRIFT) */
/** 算法类型(默认:DRIFT) */
method?: GenidMethod;
/** 起始时间戳,单位:毫秒(默认:1577836800000,即 2020-01-01 00:00:00) */
/** 起始时间戳/毫秒(默认:2020-01-01) */
baseTime?: number;
/** 工作节点 ID 的位数(范围:1-15,默认:6) */
/** 工作节点 ID 位数(1-15,默认:6) */
workerIdBitLength?: number;
/** 序列号的位数(范围:3-21,默认:6) */
/** 序列号位数(3-21,默认:6) */
seqBitLength?: number;
/** 最大序列号(默认:2^seqBitLength - 1) */
maxSeqNumber?: number;
/** 最小序列号(默认:5,0-4 保留用于时钟回拨处理) */
/** 最小序列号(默认:5,0-4 保留用于时钟回拨) */
minSeqNumber?: number;
/** 最大漂移次数,超过后等待下一毫秒(默认:2000) */
/** 最大漂移次数(默认:2000) */
topOverCostCount?: number;
}
/**
* ID 解析结果
*/
/** 内部配置(所有字段必填,由 initConfig 生成) */
interface GenidConfig {
workerId: number;
method: GenidMethod;
baseTime: number;
workerIdBitLength: number;
seqBitLength: number;
maxSeqNumber: number;
minSeqNumber: number;
topOverCostCount: number;
}
/** 内部统计数据(BigInt 确保大数精度) */
interface Stats {
totalGenerated: bigint;
overCostCount: bigint;
turnBackCount: bigint;
startTime: number;
}
/** ID 解析结果 */
interface ParseResult {
/** ID 生成时间(Date 对象) */
/** 生成时间 */
timestamp: Date;
/** ID 生成时间戳,单位:毫秒 */
/** 生成时间戳/毫秒 */
timestampMs: number;

@@ -45,58 +57,39 @@ /** 工作节点 ID */

}
/**
* 统计信息结果(对外暴露,使用 Number 类型)
*/
/** 对外统计信息 */
interface StatsResult {
/** 总生成 ID 数量 */
totalGenerated: number;
/** 漂移次数 */
overCostCount: number;
/** 时钟回拨次数 */
turnBackCount: number;
/** 运行时长,单位:毫秒 */
/** 运行时长/毫秒 */
uptimeMs: number;
/** 平均每秒生成 ID 数量 */
avgPerSecond: number;
/** 当前状态(OVER_COST: 漂移中, NORMAL: 正常) */
currentState: 'OVER_COST' | 'NORMAL';
}
/**
* 配置信息结果
*/
/** 配置信息 */
interface ConfigResult {
/** 算法类型(DRIFT: 漂移算法, TRADITIONAL: 传统算法) */
method: 'DRIFT' | 'TRADITIONAL';
/** 当前工作节点 ID */
workerId: number;
/** 工作节点 ID 范围(格式:"0-63") */
/** 格式:"0-63" */
workerIdRange: string;
/** 序列号范围(格式:"5-63") */
/** 格式:"5-63" */
sequenceRange: string;
/** 最大序列号值 */
maxSequence: number;
/** 每毫秒可生成的 ID 数量 */
idsPerMillisecond: number;
/** 起始时间(Date 对象) */
baseTime: Date;
/** 时间戳占用的位数 */
timestampBits: number;
/** 工作节点 ID 占用的位数 */
workerIdBits: number;
/** 序列号占用的位数 */
sequenceBits: number;
}
//#endregion
//#region src/index.d.ts
//#region src/genid.d.ts
/**
* 优化版 Snowflake ID 生成器
* 基于 Snowflake 算法的分布式唯一 ID 生成器
*
* 基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理。
* - 漂移算法:高并发下借用未来时间戳,突破每毫秒序列号上限
* - 时钟回拨:使用保留序列号(0-4)优雅降级,不阻塞生成
* - 非线程安全,每个 Worker/进程应使用独立实例和不同 workerId
*
* 特性:
* - 漂移算法:提升高并发下的性能
* - 优雅处理时钟回拨,不阻塞生成
* - 可配置的位长度,灵活性高
* - 支持传统和漂移两种生成方法
*
* ⚠️ 注意:此实例不是线程安全的,每个 Worker/进程应该创建独立的实例并使用不同的 workerId
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
*/

@@ -120,214 +113,54 @@ declare class GenidOptimized {

private _stats;
/**
* 构造函数,初始化 ID 生成器
*
* @param {Object} options - 配置选项
* @param {number} options.workerId - 工作节点/机器 ID(必须,范围 0 到 2^workerIdBitLength-1)
* @param {GenidMethod} [options.method=GenidMethod.DRIFT] - 算法类型
* @param {number} [options.baseTime=1577836800000] - 起始时间戳(毫秒,默认:2020-01-01)
* @param {number} [options.workerIdBitLength=6] - 工作节点 ID 的位数(1-15,默认:6)
* @param {number} [options.seqBitLength=6] - 序列号的位数(3-21,默认:6)
* @param {number} [options.maxSeqNumber] - 最大序列号(默认:2^seqBitLength-1)
* @param {number} [options.minSeqNumber=5] - 最小序列号(默认:5,0-4 保留)
* @param {number} [options.topOverCostCount=2000] - 最大漂移次数(默认:2000)
*
* @throws {Error} 如果缺少 workerId 或配置无效
*
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
*/
constructor(options: GenidOptions);
/**
* 初始化配置,设置默认值
* @private
* @param {Object} options - 用户提供的配置
* @returns {Object} 合并后的配置对象
*/
private _initConfig;
/**
* 验证配置参数的有效性
* @private
* @param {Object} config - 配置对象
* @throws {Error} 如果配置无效
*/
private _validateConfig;
/**
* 初始化实例变量
* @private
* @param {Object} config - 配置对象
*/
private _initVariables;
/**
* 获取当前时间戳(相对于 baseTime 的毫秒数)
* @private
* @returns {bigint} 当前时间戳
*/
/** 获取相对于 baseTime 的当前时间戳 */
private _getCurrentTimeTick;
/**
* 等待下一毫秒
* @private
* @returns {bigint} 下一毫秒时间戳
*/
/** 自旋等待直到时间前进到下一毫秒 */
private _getNextTimeTick;
/**
* 根据组件计算 ID
* @private
* @param {bigint} useTimeTick - 使用的时间戳
* @returns {bigint} 计算得到的 ID
*/
/** 组装 ID:timestamp | workerId | sequence,并自增序列号 */
private _calcId;
/**
* 计算时钟回拨时的 ID
* @private
* @param {bigint} useTimeTick - 使用的时间戳
* @returns {bigint} 计算得到的 ID
*/
/** 时钟回拨时组装 ID,使用保留序列号(0-4)避免冲突 */
private _calcTurnBackId;
/**
* 处理漂移情况(漂移算法)
* @private
* @returns {bigint} 生成的 ID
*/
/** 漂移状态下生成 ID */
private _nextOverCostId;
/**
* 正常生成 ID
* @private
* @returns {bigint} 生成的 ID
*/
/** 正常状态下生成 ID */
private _nextNormalId;
protected _beginOverCostAction(_useTimeTick: bigint): void;
protected _endOverCostAction(_useTimeTick: bigint): void;
protected _beginTurnBackAction(_useTimeTick: bigint): void;
protected _endTurnBackAction(_useTimeTick: bigint): void;
/**
* 钩子函数:开始漂移操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
* 生成 ID,返回 number。超出安全整数范围时抛错。
* @throws 当 ID >= Number.MAX_SAFE_INTEGER + 1 时
*/
protected _beginOverCostAction(useTimeTick: bigint): void;
/**
* 钩子函数:结束漂移操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
protected _endOverCostAction(useTimeTick: bigint): void;
/**
* 钩子函数:开始时钟回拨操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
protected _beginTurnBackAction(useTimeTick: bigint): void;
/**
* 钩子函数:结束时钟回拨操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
protected _endTurnBackAction(useTimeTick: bigint): void;
/**
* 生成下一个 ID
*
* @returns {number} 唯一 ID(Number 类型)
* @throws {Error} 如果 ID 超出 JavaScript 安全整数范围
*
* @example
* const id = genid.nextNumber();
* console.log(id); // 123456789012345
*/
nextNumber(): number;
/**
* 生成下一个 ID
*
* 如果 ID 在安全范围内返回 Number,否则返回 BigInt
*
* @returns {number|bigint} 唯一 ID
*
* @example
* const id = genid.nextId();
* console.log(typeof id); // 'number' 或 'bigint'
*/
/** 生成 ID,安全范围内返回 number,否则返回 bigint */
nextId(): number | bigint;
/**
* 生成下一个 ID
*
* @returns {bigint} 唯一 ID(BigInt 类型)
*
* @example
* const id = genid.nextBigId();
* console.log(id); // 123456789012345678n
*/
/** 生成 ID,始终返回 bigint */
nextBigId(): bigint;
/**
* 批量生成 ID
*
* @param {number} count - 要生成的 ID 数量
* @param {boolean} [asBigInt=false] - 是否返回 BigInt 数组
* @returns {Array<number|bigint>} 唯一 ID 数组
*
* @example
* const ids = genid.nextBatch(100);
* const bigIds = genid.nextBatch(100, true);
*/
/** 批量生成 ID */
nextBatch(count: number, asBigInt?: boolean): Array<number | bigint>;
/**
* 解析 ID,提取其组成部分
* 解析 ID,提取时间戳、workerId、序列号
*
* @param {number|bigint|string} id - 要解析的 ID
* @returns {Object} 解析结果
* @returns {Date} return.timestamp - 生成时间戳
* @returns {number} return.timestampMs - 时间戳(毫秒)
* @returns {number} return.workerId - 工作节点 ID
* @returns {number} return.sequence - 序列号
*
* @example
* const info = genid.parse(id);
* console.log(info);
* // {
* // timestamp: Date,
* // timestampMs: 1609459200000,
* // workerId: 1,
* // sequence: 42
* // }
* genid.parse(id)
* // { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
*/
parse(id: number | bigint | string): ParseResult;
/**
* 获取生成器统计信息
*
* @returns {Object} 统计数据
*
* @example
* const stats = genid.getStats();
* console.log(stats);
*/
/** 获取运行统计信息 */
getStats(): StatsResult;
/**
* 重置统计数据
*/
/** 重置统计数据 */
resetStats(): void;
/**
* 获取配置信息
*
* @returns {Object} 配置详情
*/
/** 获取当前配置信息 */
getConfig(): ConfigResult;
/**
* 验证 ID 是否为有效的 Snowflake ID
*
* @param {number|bigint|string} id - 要验证的 ID
* @param {boolean} [strictWorkerId=false] - 是否严格验证 workerId 必须匹配当前实例
* @returns {boolean} ID 是否有效
*
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
* genid.isValid(id); // true
* genid.isValid(12345); // false
* genid.isValid(id, true); // true (workerId 匹配)
* 验证 ID 是否为当前配置下合法的 Snowflake ID
* @param strictWorkerId - 为 true 时要求 workerId 匹配当前实例
*/
isValid(id: number | bigint | string, strictWorkerId?: boolean): boolean;
/**
* 将 ID 格式化为二进制字符串以便调试
*
* @param {number|bigint|string} id - 要格式化的 ID
* @returns {string} 格式化的二进制表示
*/
/** 将 ID 格式化为带标注的二进制字符串(调试用) */
formatBinary(id: number | bigint | string): string;
}
//#endregion
export { GenidOptimized };
export { ConfigResult, GenidConfig, GenidMethod, GenidOptimized, GenidOptions, ParseResult, Stats, StatsResult };

@@ -1,39 +0,51 @@

//#region src/types/index.d.ts
/**
* ID 生成算法类型
*/
//#region src/types.d.ts
/** ID 生成算法类型 */
declare enum GenidMethod {
/** 漂移算法(推荐用于高性能场景) */
/** 漂移算法(推荐,高并发下可突破每毫秒序列号上限) */
DRIFT = 1,
/** 传统算法 */
/** 传统算法(序列号耗尽时等待下一毫秒) */
TRADITIONAL = 2
}
/**
* ID 生成器配置选项
*/
/** ID 生成器构造选项 */
interface GenidOptions {
/** 工作节点/机器 ID(必须,范围 0 到 2^workerIdBitLength-1) */
/** 工作节点 ID(必须,范围 0 到 2^workerIdBitLength-1) */
workerId: number;
/** 算法类型(默认:GenidMethod.DRIFT) */
/** 算法类型(默认:DRIFT) */
method?: GenidMethod;
/** 起始时间戳,单位:毫秒(默认:1577836800000,即 2020-01-01 00:00:00) */
/** 起始时间戳/毫秒(默认:2020-01-01) */
baseTime?: number;
/** 工作节点 ID 的位数(范围:1-15,默认:6) */
/** 工作节点 ID 位数(1-15,默认:6) */
workerIdBitLength?: number;
/** 序列号的位数(范围:3-21,默认:6) */
/** 序列号位数(3-21,默认:6) */
seqBitLength?: number;
/** 最大序列号(默认:2^seqBitLength - 1) */
maxSeqNumber?: number;
/** 最小序列号(默认:5,0-4 保留用于时钟回拨处理) */
/** 最小序列号(默认:5,0-4 保留用于时钟回拨) */
minSeqNumber?: number;
/** 最大漂移次数,超过后等待下一毫秒(默认:2000) */
/** 最大漂移次数(默认:2000) */
topOverCostCount?: number;
}
/**
* ID 解析结果
*/
/** 内部配置(所有字段必填,由 initConfig 生成) */
interface GenidConfig {
workerId: number;
method: GenidMethod;
baseTime: number;
workerIdBitLength: number;
seqBitLength: number;
maxSeqNumber: number;
minSeqNumber: number;
topOverCostCount: number;
}
/** 内部统计数据(BigInt 确保大数精度) */
interface Stats {
totalGenerated: bigint;
overCostCount: bigint;
turnBackCount: bigint;
startTime: number;
}
/** ID 解析结果 */
interface ParseResult {
/** ID 生成时间(Date 对象) */
/** 生成时间 */
timestamp: Date;
/** ID 生成时间戳,单位:毫秒 */
/** 生成时间戳/毫秒 */
timestampMs: number;

@@ -45,58 +57,39 @@ /** 工作节点 ID */

}
/**
* 统计信息结果(对外暴露,使用 Number 类型)
*/
/** 对外统计信息 */
interface StatsResult {
/** 总生成 ID 数量 */
totalGenerated: number;
/** 漂移次数 */
overCostCount: number;
/** 时钟回拨次数 */
turnBackCount: number;
/** 运行时长,单位:毫秒 */
/** 运行时长/毫秒 */
uptimeMs: number;
/** 平均每秒生成 ID 数量 */
avgPerSecond: number;
/** 当前状态(OVER_COST: 漂移中, NORMAL: 正常) */
currentState: 'OVER_COST' | 'NORMAL';
}
/**
* 配置信息结果
*/
/** 配置信息 */
interface ConfigResult {
/** 算法类型(DRIFT: 漂移算法, TRADITIONAL: 传统算法) */
method: 'DRIFT' | 'TRADITIONAL';
/** 当前工作节点 ID */
workerId: number;
/** 工作节点 ID 范围(格式:"0-63") */
/** 格式:"0-63" */
workerIdRange: string;
/** 序列号范围(格式:"5-63") */
/** 格式:"5-63" */
sequenceRange: string;
/** 最大序列号值 */
maxSequence: number;
/** 每毫秒可生成的 ID 数量 */
idsPerMillisecond: number;
/** 起始时间(Date 对象) */
baseTime: Date;
/** 时间戳占用的位数 */
timestampBits: number;
/** 工作节点 ID 占用的位数 */
workerIdBits: number;
/** 序列号占用的位数 */
sequenceBits: number;
}
//#endregion
//#region src/index.d.ts
//#region src/genid.d.ts
/**
* 优化版 Snowflake ID 生成器
* 基于 Snowflake 算法的分布式唯一 ID 生成器
*
* 基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理。
* - 漂移算法:高并发下借用未来时间戳,突破每毫秒序列号上限
* - 时钟回拨:使用保留序列号(0-4)优雅降级,不阻塞生成
* - 非线程安全,每个 Worker/进程应使用独立实例和不同 workerId
*
* 特性:
* - 漂移算法:提升高并发下的性能
* - 优雅处理时钟回拨,不阻塞生成
* - 可配置的位长度,灵活性高
* - 支持传统和漂移两种生成方法
*
* ⚠️ 注意:此实例不是线程安全的,每个 Worker/进程应该创建独立的实例并使用不同的 workerId
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
*/

@@ -120,214 +113,54 @@ declare class GenidOptimized {

private _stats;
/**
* 构造函数,初始化 ID 生成器
*
* @param {Object} options - 配置选项
* @param {number} options.workerId - 工作节点/机器 ID(必须,范围 0 到 2^workerIdBitLength-1)
* @param {GenidMethod} [options.method=GenidMethod.DRIFT] - 算法类型
* @param {number} [options.baseTime=1577836800000] - 起始时间戳(毫秒,默认:2020-01-01)
* @param {number} [options.workerIdBitLength=6] - 工作节点 ID 的位数(1-15,默认:6)
* @param {number} [options.seqBitLength=6] - 序列号的位数(3-21,默认:6)
* @param {number} [options.maxSeqNumber] - 最大序列号(默认:2^seqBitLength-1)
* @param {number} [options.minSeqNumber=5] - 最小序列号(默认:5,0-4 保留)
* @param {number} [options.topOverCostCount=2000] - 最大漂移次数(默认:2000)
*
* @throws {Error} 如果缺少 workerId 或配置无效
*
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
*/
constructor(options: GenidOptions);
/**
* 初始化配置,设置默认值
* @private
* @param {Object} options - 用户提供的配置
* @returns {Object} 合并后的配置对象
*/
private _initConfig;
/**
* 验证配置参数的有效性
* @private
* @param {Object} config - 配置对象
* @throws {Error} 如果配置无效
*/
private _validateConfig;
/**
* 初始化实例变量
* @private
* @param {Object} config - 配置对象
*/
private _initVariables;
/**
* 获取当前时间戳(相对于 baseTime 的毫秒数)
* @private
* @returns {bigint} 当前时间戳
*/
/** 获取相对于 baseTime 的当前时间戳 */
private _getCurrentTimeTick;
/**
* 等待下一毫秒
* @private
* @returns {bigint} 下一毫秒时间戳
*/
/** 自旋等待直到时间前进到下一毫秒 */
private _getNextTimeTick;
/**
* 根据组件计算 ID
* @private
* @param {bigint} useTimeTick - 使用的时间戳
* @returns {bigint} 计算得到的 ID
*/
/** 组装 ID:timestamp | workerId | sequence,并自增序列号 */
private _calcId;
/**
* 计算时钟回拨时的 ID
* @private
* @param {bigint} useTimeTick - 使用的时间戳
* @returns {bigint} 计算得到的 ID
*/
/** 时钟回拨时组装 ID,使用保留序列号(0-4)避免冲突 */
private _calcTurnBackId;
/**
* 处理漂移情况(漂移算法)
* @private
* @returns {bigint} 生成的 ID
*/
/** 漂移状态下生成 ID */
private _nextOverCostId;
/**
* 正常生成 ID
* @private
* @returns {bigint} 生成的 ID
*/
/** 正常状态下生成 ID */
private _nextNormalId;
protected _beginOverCostAction(_useTimeTick: bigint): void;
protected _endOverCostAction(_useTimeTick: bigint): void;
protected _beginTurnBackAction(_useTimeTick: bigint): void;
protected _endTurnBackAction(_useTimeTick: bigint): void;
/**
* 钩子函数:开始漂移操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
* 生成 ID,返回 number。超出安全整数范围时抛错。
* @throws 当 ID >= Number.MAX_SAFE_INTEGER + 1 时
*/
protected _beginOverCostAction(useTimeTick: bigint): void;
/**
* 钩子函数:结束漂移操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
protected _endOverCostAction(useTimeTick: bigint): void;
/**
* 钩子函数:开始时钟回拨操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
protected _beginTurnBackAction(useTimeTick: bigint): void;
/**
* 钩子函数:结束时钟回拨操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
protected _endTurnBackAction(useTimeTick: bigint): void;
/**
* 生成下一个 ID
*
* @returns {number} 唯一 ID(Number 类型)
* @throws {Error} 如果 ID 超出 JavaScript 安全整数范围
*
* @example
* const id = genid.nextNumber();
* console.log(id); // 123456789012345
*/
nextNumber(): number;
/**
* 生成下一个 ID
*
* 如果 ID 在安全范围内返回 Number,否则返回 BigInt
*
* @returns {number|bigint} 唯一 ID
*
* @example
* const id = genid.nextId();
* console.log(typeof id); // 'number' 或 'bigint'
*/
/** 生成 ID,安全范围内返回 number,否则返回 bigint */
nextId(): number | bigint;
/**
* 生成下一个 ID
*
* @returns {bigint} 唯一 ID(BigInt 类型)
*
* @example
* const id = genid.nextBigId();
* console.log(id); // 123456789012345678n
*/
/** 生成 ID,始终返回 bigint */
nextBigId(): bigint;
/**
* 批量生成 ID
*
* @param {number} count - 要生成的 ID 数量
* @param {boolean} [asBigInt=false] - 是否返回 BigInt 数组
* @returns {Array<number|bigint>} 唯一 ID 数组
*
* @example
* const ids = genid.nextBatch(100);
* const bigIds = genid.nextBatch(100, true);
*/
/** 批量生成 ID */
nextBatch(count: number, asBigInt?: boolean): Array<number | bigint>;
/**
* 解析 ID,提取其组成部分
* 解析 ID,提取时间戳、workerId、序列号
*
* @param {number|bigint|string} id - 要解析的 ID
* @returns {Object} 解析结果
* @returns {Date} return.timestamp - 生成时间戳
* @returns {number} return.timestampMs - 时间戳(毫秒)
* @returns {number} return.workerId - 工作节点 ID
* @returns {number} return.sequence - 序列号
*
* @example
* const info = genid.parse(id);
* console.log(info);
* // {
* // timestamp: Date,
* // timestampMs: 1609459200000,
* // workerId: 1,
* // sequence: 42
* // }
* genid.parse(id)
* // { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
*/
parse(id: number | bigint | string): ParseResult;
/**
* 获取生成器统计信息
*
* @returns {Object} 统计数据
*
* @example
* const stats = genid.getStats();
* console.log(stats);
*/
/** 获取运行统计信息 */
getStats(): StatsResult;
/**
* 重置统计数据
*/
/** 重置统计数据 */
resetStats(): void;
/**
* 获取配置信息
*
* @returns {Object} 配置详情
*/
/** 获取当前配置信息 */
getConfig(): ConfigResult;
/**
* 验证 ID 是否为有效的 Snowflake ID
*
* @param {number|bigint|string} id - 要验证的 ID
* @param {boolean} [strictWorkerId=false] - 是否严格验证 workerId 必须匹配当前实例
* @returns {boolean} ID 是否有效
*
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
* genid.isValid(id); // true
* genid.isValid(12345); // false
* genid.isValid(id, true); // true (workerId 匹配)
* 验证 ID 是否为当前配置下合法的 Snowflake ID
* @param strictWorkerId - 为 true 时要求 workerId 匹配当前实例
*/
isValid(id: number | bigint | string, strictWorkerId?: boolean): boolean;
/**
* 将 ID 格式化为二进制字符串以便调试
*
* @param {number|bigint|string} id - 要格式化的 ID
* @returns {string} 格式化的二进制表示
*/
/** 将 ID 格式化为带标注的二进制字符串(调试用) */
formatBinary(id: number | bigint | string): string;
}
//#endregion
export { GenidOptimized };
export { ConfigResult, GenidConfig, GenidMethod, GenidOptimized, GenidOptions, ParseResult, Stats, StatsResult };

@@ -1,27 +0,53 @@

//#region src/types/index.ts
/**
* ID 生成算法类型
*/
//#region src/types.ts
/** ID 生成算法类型 */
let GenidMethod = /* @__PURE__ */ function(GenidMethod) {
/** 漂移算法(推荐用于高性能场景) */
/** 漂移算法(推荐,高并发下可突破每毫秒序列号上限) */
GenidMethod[GenidMethod["DRIFT"] = 1] = "DRIFT";
/** 传统算法 */
/** 传统算法(序列号耗尽时等待下一毫秒) */
GenidMethod[GenidMethod["TRADITIONAL"] = 2] = "TRADITIONAL";
return GenidMethod;
}({});
//#endregion
//#region src/index.ts
//#region src/config.ts
/** 将用户配置与默认值合并,返回完整内部配置 */
function initConfig(options) {
const config = {
workerId: options.workerId,
method: options.method === GenidMethod.TRADITIONAL ? GenidMethod.TRADITIONAL : GenidMethod.DRIFT,
baseTime: options.baseTime && options.baseTime > 0 ? options.baseTime : (/* @__PURE__ */ new Date("2020-01-01")).valueOf(),
workerIdBitLength: options.workerIdBitLength && options.workerIdBitLength > 0 ? options.workerIdBitLength : 6,
seqBitLength: options.seqBitLength && options.seqBitLength > 0 ? options.seqBitLength : 6,
maxSeqNumber: 0,
minSeqNumber: 0,
topOverCostCount: 0
};
config.maxSeqNumber = options.maxSeqNumber && options.maxSeqNumber > 0 ? options.maxSeqNumber : (1 << config.seqBitLength) - 1;
config.minSeqNumber = options.minSeqNumber && options.minSeqNumber > 0 ? options.minSeqNumber : 5;
config.topOverCostCount = options.topOverCostCount && options.topOverCostCount > 0 ? options.topOverCostCount : 2e3;
return config;
}
/** 校验配置合法性,不合法则抛出 Error */
function validateConfig(config) {
const { workerId, baseTime, workerIdBitLength, seqBitLength, minSeqNumber, maxSeqNumber } = config;
if (baseTime > Date.now()) throw new Error("[GenidOptimized] baseTime 不能大于当前时间");
if (workerIdBitLength < 1 || workerIdBitLength > 15) throw new Error("[GenidOptimized] workerIdBitLength 必须在 1 到 15 之间");
if (seqBitLength < 3 || seqBitLength > 21) throw new Error("[GenidOptimized] seqBitLength 必须在 3 到 21 之间");
if (workerIdBitLength + seqBitLength > 22) throw new Error("[GenidOptimized] workerIdBitLength + seqBitLength 不能超过 22");
const maxWorkerId = (1 << workerIdBitLength) - 1;
if (workerId < 0 || workerId > maxWorkerId) throw new Error(`[GenidOptimized] workerId 必须在 0 到 ${maxWorkerId} 之间`);
if (minSeqNumber < 5) throw new Error("[GenidOptimized] minSeqNumber 必须至少为 5(0-4 保留)");
if (maxSeqNumber < minSeqNumber) throw new Error("[GenidOptimized] maxSeqNumber 必须大于或等于 minSeqNumber");
}
//#endregion
//#region src/genid.ts
/**
* 优化版 Snowflake ID 生成器
* 基于 Snowflake 算法的分布式唯一 ID 生成器
*
* 基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理。
* - 漂移算法:高并发下借用未来时间戳,突破每毫秒序列号上限
* - 时钟回拨:使用保留序列号(0-4)优雅降级,不阻塞生成
* - 非线程安全,每个 Worker/进程应使用独立实例和不同 workerId
*
* 特性:
* - 漂移算法:提升高并发下的性能
* - 优雅处理时钟回拨,不阻塞生成
* - 可配置的位长度,灵活性高
* - 支持传统和漂移两种生成方法
*
* ⚠️ 注意:此实例不是线程安全的,每个 Worker/进程应该创建独立的实例并使用不同的 workerId
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
*/

@@ -45,25 +71,6 @@ var GenidOptimized = class {

_stats;
/**
* 构造函数,初始化 ID 生成器
*
* @param {Object} options - 配置选项
* @param {number} options.workerId - 工作节点/机器 ID(必须,范围 0 到 2^workerIdBitLength-1)
* @param {GenidMethod} [options.method=GenidMethod.DRIFT] - 算法类型
* @param {number} [options.baseTime=1577836800000] - 起始时间戳(毫秒,默认:2020-01-01)
* @param {number} [options.workerIdBitLength=6] - 工作节点 ID 的位数(1-15,默认:6)
* @param {number} [options.seqBitLength=6] - 序列号的位数(3-21,默认:6)
* @param {number} [options.maxSeqNumber] - 最大序列号(默认:2^seqBitLength-1)
* @param {number} [options.minSeqNumber=5] - 最小序列号(默认:5,0-4 保留)
* @param {number} [options.topOverCostCount=2000] - 最大漂移次数(默认:2000)
*
* @throws {Error} 如果缺少 workerId 或配置无效
*
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
*/
constructor(options) {
if (options.workerId === void 0 || options.workerId === null) throw new Error("[GenidOptimized] workerId 是必须参数");
const config = this._initConfig(options);
this._validateConfig(config);
const config = initConfig(options);
validateConfig(config);
this._initVariables(config);

@@ -77,45 +84,2 @@ this._stats = {

}
/**
* 初始化配置,设置默认值
* @private
* @param {Object} options - 用户提供的配置
* @returns {Object} 合并后的配置对象
*/
_initConfig(options) {
const config = {
workerId: options.workerId,
method: options.method === GenidMethod.TRADITIONAL ? GenidMethod.TRADITIONAL : GenidMethod.DRIFT,
baseTime: options.baseTime && options.baseTime > 0 ? options.baseTime : (/* @__PURE__ */ new Date("2020-01-01")).valueOf(),
workerIdBitLength: options.workerIdBitLength && options.workerIdBitLength > 0 ? options.workerIdBitLength : 6,
seqBitLength: options.seqBitLength && options.seqBitLength > 0 ? options.seqBitLength : 6,
maxSeqNumber: 0,
minSeqNumber: 0,
topOverCostCount: 0
};
config.maxSeqNumber = options.maxSeqNumber && options.maxSeqNumber > 0 ? options.maxSeqNumber : (1 << config.seqBitLength) - 1;
config.minSeqNumber = options.minSeqNumber && options.minSeqNumber > 0 ? options.minSeqNumber : 5;
config.topOverCostCount = options.topOverCostCount && options.topOverCostCount > 0 ? options.topOverCostCount : 2e3;
return config;
}
/**
* 验证配置参数的有效性
* @private
* @param {Object} config - 配置对象
* @throws {Error} 如果配置无效
*/
_validateConfig(config) {
const { workerId, workerIdBitLength, seqBitLength, minSeqNumber, maxSeqNumber } = config;
if (workerIdBitLength < 1 || workerIdBitLength > 15) throw new Error("[GenidOptimized] workerIdBitLength 必须在 1 到 15 之间");
if (seqBitLength < 3 || seqBitLength > 21) throw new Error("[GenidOptimized] seqBitLength 必须在 3 到 21 之间");
if (workerIdBitLength + seqBitLength > 22) throw new Error("[GenidOptimized] workerIdBitLength + seqBitLength 不能超过 22");
const maxWorkerId = (1 << workerIdBitLength) - 1;
if (workerId < 0 || workerId > maxWorkerId) throw new Error(`[GenidOptimized] workerId 必须在 0 到 ${maxWorkerId} 之间`);
if (minSeqNumber < 5) throw new Error("[GenidOptimized] minSeqNumber 必须至少为 5(0-4 保留)");
if (maxSeqNumber < minSeqNumber) throw new Error("[GenidOptimized] maxSeqNumber 必须大于或等于 minSeqNumber");
}
/**
* 初始化实例变量
* @private
* @param {Object} config - 配置对象
*/
_initVariables(config) {

@@ -138,15 +102,7 @@ this.method = BigInt(config.method);

}
/**
* 获取当前时间戳(相对于 baseTime 的毫秒数)
* @private
* @returns {bigint} 当前时间戳
*/
/** 获取相对于 baseTime 的当前时间戳 */
_getCurrentTimeTick() {
return BigInt(Date.now()) - this.baseTime;
}
/**
* 等待下一毫秒
* @private
* @returns {bigint} 下一毫秒时间戳
*/
/** 自旋等待直到时间前进到下一毫秒 */
_getNextTimeTick() {

@@ -158,8 +114,3 @@ let timeTick = this._getCurrentTimeTick();

spinCount++;
if (spinCount > maxSpinCount)
/**
* 如果自旋太多次,强制返回当前时间 + 1
* 这种情况理论上不应该发生,除非系统时间出现严重问题
*/
return this._lastTimeTick + 1n;
if (spinCount > maxSpinCount) return this._lastTimeTick + 1n;
timeTick = this._getCurrentTimeTick();

@@ -169,8 +120,3 @@ }

}
/**
* 根据组件计算 ID
* @private
* @param {bigint} useTimeTick - 使用的时间戳
* @returns {bigint} 计算得到的 ID
*/
/** 组装 ID:timestamp | workerId | sequence,并自增序列号 */
_calcId(useTimeTick) {

@@ -182,8 +128,3 @@ const result = (BigInt(useTimeTick) << this._timestampShift) + (this.workerId << this.seqBitLength) + this._currentSeqNumber;

}
/**
* 计算时钟回拨时的 ID
* @private
* @param {bigint} useTimeTick - 使用的时间戳
* @returns {bigint} 计算得到的 ID
*/
/** 时钟回拨时组装 ID,使用保留序列号(0-4)避免冲突 */
_calcTurnBackId(useTimeTick) {

@@ -195,7 +136,3 @@ const result = (BigInt(useTimeTick) << this._timestampShift) + (this.workerId << this.seqBitLength) + BigInt(this._turnBackIndex);

}
/**
* 处理漂移情况(漂移算法)
* @private
* @returns {bigint} 生成的 ID
*/
/** 漂移状态下生成 ID */
_nextOverCostId() {

@@ -236,7 +173,3 @@ const currentTimeTick = this._getCurrentTimeTick();

}
/**
* 正常生成 ID
* @private
* @returns {bigint} 生成的 ID
*/
/** 正常状态下生成 ID */
_nextNormalId() {

@@ -258,2 +191,9 @@ const currentTimeTick = this._getCurrentTimeTick();

}
if (this._turnBackTimeTick >= this._lastTimeTick) {
this._turnBackTimeTick = 0n;
this._turnBackIndex = 0;
this._lastTimeTick = this._getNextTimeTick();
this._currentSeqNumber = this.minSeqNumber;
return this._calcId(this._lastTimeTick);
}
return this._calcTurnBackId(this._turnBackTimeTick);

@@ -272,2 +212,7 @@ }

if (this._currentSeqNumber > this.maxSeqNumber) {
if (this.method === BigInt(GenidMethod.TRADITIONAL)) {
this._lastTimeTick = this._getNextTimeTick();
this._currentSeqNumber = this.minSeqNumber;
return this._calcId(this._lastTimeTick);
}
this._beginOverCostAction(currentTimeTick);

@@ -283,36 +228,10 @@ this._lastTimeTick++;

}
_beginOverCostAction(_useTimeTick) {}
_endOverCostAction(_useTimeTick) {}
_beginTurnBackAction(_useTimeTick) {}
_endTurnBackAction(_useTimeTick) {}
/**
* 钩子函数:开始漂移操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
* 生成 ID,返回 number。超出安全整数范围时抛错。
* @throws 当 ID >= Number.MAX_SAFE_INTEGER + 1 时
*/
_beginOverCostAction(useTimeTick) {}
/**
* 钩子函数:结束漂移操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
_endOverCostAction(useTimeTick) {}
/**
* 钩子函数:开始时钟回拨操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
_beginTurnBackAction(useTimeTick) {}
/**
* 钩子函数:结束时钟回拨操作(可被子类重写)
* @protected
* @param {bigint} useTimeTick - 当前时间戳
*/
_endTurnBackAction(useTimeTick) {}
/**
* 生成下一个 ID
*
* @returns {number} 唯一 ID(Number 类型)
* @throws {Error} 如果 ID 超出 JavaScript 安全整数范围
*
* @example
* const id = genid.nextNumber();
* console.log(id); // 123456789012345
*/
nextNumber() {

@@ -323,13 +242,3 @@ const id = this._isOverCost ? this._nextOverCostId() : this._nextNormalId();

}
/**
* 生成下一个 ID
*
* 如果 ID 在安全范围内返回 Number,否则返回 BigInt
*
* @returns {number|bigint} 唯一 ID
*
* @example
* const id = genid.nextId();
* console.log(typeof id); // 'number' 或 'bigint'
*/
/** 生成 ID,安全范围内返回 number,否则返回 bigint */
nextId() {

@@ -339,25 +248,7 @@ const id = this._isOverCost ? this._nextOverCostId() : this._nextNormalId();

}
/**
* 生成下一个 ID
*
* @returns {bigint} 唯一 ID(BigInt 类型)
*
* @example
* const id = genid.nextBigId();
* console.log(id); // 123456789012345678n
*/
/** 生成 ID,始终返回 bigint */
nextBigId() {
return this._isOverCost ? this._nextOverCostId() : this._nextNormalId();
}
/**
* 批量生成 ID
*
* @param {number} count - 要生成的 ID 数量
* @param {boolean} [asBigInt=false] - 是否返回 BigInt 数组
* @returns {Array<number|bigint>} 唯一 ID 数组
*
* @example
* const ids = genid.nextBatch(100);
* const bigIds = genid.nextBatch(100, true);
*/
/** 批量生成 ID */
nextBatch(count, asBigInt = false) {

@@ -370,20 +261,7 @@ if (count <= 0) throw new Error("[GenidOptimized] 批量生成数量必须大于 0");

/**
* 解析 ID,提取其组成部分
* 解析 ID,提取时间戳、workerId、序列号
*
* @param {number|bigint|string} id - 要解析的 ID
* @returns {Object} 解析结果
* @returns {Date} return.timestamp - 生成时间戳
* @returns {number} return.timestampMs - 时间戳(毫秒)
* @returns {number} return.workerId - 工作节点 ID
* @returns {number} return.sequence - 序列号
*
* @example
* const info = genid.parse(id);
* console.log(info);
* // {
* // timestamp: Date,
* // timestampMs: 1609459200000,
* // workerId: 1,
* // sequence: 42
* // }
* genid.parse(id)
* // { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
*/

@@ -404,11 +282,3 @@ parse(id) {

}
/**
* 获取生成器统计信息
*
* @returns {Object} 统计数据
*
* @example
* const stats = genid.getStats();
* console.log(stats);
*/
/** 获取运行统计信息 */
getStats() {

@@ -426,5 +296,3 @@ const uptime = Date.now() - this._stats.startTime;

}
/**
* 重置统计数据
*/
/** 重置统计数据 */
resetStats() {

@@ -438,7 +306,3 @@ this._stats = {

}
/**
* 获取配置信息
*
* @returns {Object} 配置详情
*/
/** 获取当前配置信息 */
getConfig() {

@@ -462,14 +326,4 @@ const maxWorkerId = (1 << Number(this.workerIdBitLength)) - 1;

/**
* 验证 ID 是否为有效的 Snowflake ID
*
* @param {number|bigint|string} id - 要验证的 ID
* @param {boolean} [strictWorkerId=false] - 是否严格验证 workerId 必须匹配当前实例
* @returns {boolean} ID 是否有效
*
* @example
* const genid = new GenidOptimized({ workerId: 1 });
* const id = genid.nextId();
* genid.isValid(id); // true
* genid.isValid(12345); // false
* genid.isValid(id, true); // true (workerId 匹配)
* 验证 ID 是否为当前配置下合法的 Snowflake ID
* @param strictWorkerId - 为 true 时要求 workerId 匹配当前实例
*/

@@ -497,8 +351,3 @@ isValid(id, strictWorkerId = false) {

}
/**
* 将 ID 格式化为二进制字符串以便调试
*
* @param {number|bigint|string} id - 要格式化的 ID
* @returns {string} 格式化的二进制表示
*/
/** 将 ID 格式化为带标注的二进制字符串(调试用) */
formatBinary(id) {

@@ -521,4 +370,3 @@ const idBigInt = BigInt(id);

};
//#endregion
export { GenidOptimized };
export { GenidMethod, GenidOptimized };
{
"name": "@cdlab996/genid",
"type": "module",
"version": "1.2.1",
"version": "1.3.0",
"description": "基于 Snowflake 算法的高性能分布式唯一 ID 生成器",

@@ -50,7 +50,7 @@ "author": "wudi <wuchendi96@gmail.com>",

"devDependencies": {
"@biomejs/biome": "^2.3.14",
"@biomejs/biome": "^2.4.7",
"@types/node": "^25",
"tsdown": "^0.20.3",
"tsdown": "^0.21.4",
"typescript": "^5",
"vitest": "^4.0.18"
"vitest": "^4.1.0"
},

@@ -57,0 +57,0 @@ "publishConfig": {

+141
-244
# @cdlab996/genid
基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理,适用于分布式系统中的唯一标识生成需求。
[![npm version](https://img.shields.io/npm/v/@cdlab996/genid)](https://www.npmjs.com/package/@cdlab996/genid)
[![license](https://img.shields.io/npm/l/@cdlab996/genid)](./LICENSE)
基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理。
## 特性
- 🚀 **漂移算法**:高并发场景下性能优异
- 🔄 **时钟回拨处理**:优雅处理时钟回拨,不阻塞 ID 生成
- ⚙️ **灵活配置**:支持自定义位长度分配
- 📊 **性能监控**:内置统计和调试功能
- ✅ **ID 验证**:验证 ID 的有效性,支持严格/宽松模式
- **漂移算法** - 高并发场景下突破每毫秒序列号上限,性能更优
- **时钟回拨处理** - 使用保留序列号优雅降级,不阻塞 ID 生成
- **灵活配置** - 支持自定义时间戳、节点 ID、序列号的位长度分配
- **ID 验证** - 支持严格/宽松模式校验 ID 有效性
- **运行监控** - 内置统计、解析和二进制格式化调试工具
## 架构设计
## 安装
### 核心流程
```bash
# npm
npm install @cdlab996/genid
```mermaid
graph TB
A[开始生成 ID] --> B{是否处于漂移状态?}
B -->|否| C[正常路径]
B -->|是| D[漂移路径]
C --> E{检测时钟}
E -->|时钟回拨| F[使用保留序列号 0-4]
E -->|时间前进| G[重置序列号]
E -->|同一毫秒| H{序列号是否溢出?}
H -->|否| I[序列号+1 正常生成]
H -->|是| J[进入漂移状态 时间戳+1]
D --> K{检测时间}
K -->|时间追上| L[退出漂移 恢复正常]
K -->|超过最大漂移| M[等待下一毫秒 退出漂移]
K -->|继续漂移| N{序列号是否溢出?}
N -->|否| O[使用当前序列号]
N -->|是| P[时间戳+1 重置序列号]
F --> Q[计算 ID]
G --> Q
I --> Q
J --> Q
L --> Q
M --> Q
O --> Q
P --> Q
Q --> R[更新统计]
R --> S[返回 ID]
# pnpm
pnpm add @cdlab996/genid
```
### ID 结构(64-bit)
```
|------------ 时间戳 ------------|-- 工作节点 ID --|-- 序列号 --|
42-52 bits 1-15 bits 3-21 bits
```
**位分配示例(默认配置):**
- 时间戳:52 bits(可用约 139 年)
- 工作节点 ID:6 bits(支持 64 个节点)
- 序列号:6 bits(每毫秒 59 个 ID,5-63)
**序列号分配:**
- `0-4`:保留用于时钟回拨
- `5-maxSeqNumber`:正常使用
## 快速开始

@@ -81,143 +36,73 @@

const id = genid.nextId()
console.log(id) // 123456789012345
```
## API 参考
// 批量生成
const ids = genid.nextBatch(1000)
### 构造函数
// 解析 ID
const info = genid.parse(id)
// => { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
```typescript
new GenidOptimized(options: GenidOptions)
// 验证 ID
genid.isValid(id) // true
```
**配置选项**
## API
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `workerId` | number | ✅ | - | 工作节点 ID(范围:0 到 2^workerIdBitLength-1) |
| `method` | GenidMethod | ❌ | `DRIFT` | 算法类型:`DRIFT` 或 `TRADITIONAL` |
| `baseTime` | number | ❌ | `1577836800000` | 起始时间戳(毫秒,默认:2020-01-01) |
| `workerIdBitLength` | number | ❌ | `6` | 工作节点 ID 位数(1-15) |
| `seqBitLength` | number | ❌ | `6` | 序列号位数(3-21) |
| `maxSeqNumber` | number | ❌ | `2^seqBitLength-1` | 最大序列号 |
| `minSeqNumber` | number | ❌ | `5` | 最小序列号(0-4 保留用于时钟回拨) |
| `topOverCostCount` | number | ❌ | `2000` | 最大漂移次数 |
### `new GenidOptimized(options)`
| 参数 | 类型 | 必填 | 默认值 | 说明 |
| ------------------- | ------------- | :---: | ------------------ | --------------------------------------------- |
| `workerId` | `number` | Yes | - | 工作节点 ID(0 ~ 2^workerIdBitLength-1) |
| `method` | `GenidMethod` | | `DRIFT` | 算法:`DRIFT`(漂移)或 `TRADITIONAL`(传统) |
| `baseTime` | `number` | | `1577836800000` | 起始时间戳,毫秒(默认 2020-01-01) |
| `workerIdBitLength` | `number` | | `6` | 节点 ID 位数(1-15) |
| `seqBitLength` | `number` | | `6` | 序列号位数(3-21) |
| `maxSeqNumber` | `number` | | `2^seqBitLength-1` | 最大序列号 |
| `minSeqNumber` | `number` | | `5` | 最小序列号(0-4 保留用于时钟回拨) |
| `topOverCostCount` | `number` | | `2000` | 最大漂移次数 |
### 生成 ID
#### `nextId()`
返回 Number 或 BigInt 类型的 ID(自动选择)
```typescript
const id = genid.nextId()
genid.nextId() // 返回 number | bigint(自动选择)
genid.nextNumber() // 返回 number(超出安全整数范围抛错)
genid.nextBigId() // 返回 bigint
genid.nextBatch(100) // 批量生成 100 个 ID
genid.nextBatch(100, true) // 批量生成 100 个 BigInt ID
```
#### `nextNumber()`
### 解析与验证
返回 Number 类型的 ID(超出安全范围会抛出错误)
```typescript
const id = genid.nextNumber()
```
// 解析 ID 的组成部分
genid.parse(id)
// => { timestamp: Date, timestampMs: number, workerId: number, sequence: number }
#### `nextBigId()`
// 宽松验证:检查 ID 格式是否有效
genid.isValid(id) // true
genid.isValid(12345) // false
genid.isValid('invalid') // false
返回 BigInt 类型的 ID
```typescript
const id = genid.nextBigId()
// 严格验证:要求 workerId 匹配当前实例
genid.isValid(id, true) // true(本实例生成的 ID)
genid.isValid(otherId, true) // false(其他实例生成的 ID)
```
#### `nextBatch(count, asBigInt?)`
批量生成 ID
```typescript
const ids = genid.nextBatch(100) // 生成 100 个 ID
const bigIds = genid.nextBatch(100, true) // 生成 100 个 BigInt ID
```
### 解析 ID
#### `parse(id)`
解析 ID,提取组成部分
```typescript
const info = genid.parse(id)
console.log(info)
// {
// timestamp: Date, // 生成时间
// timestampMs: 1609459200000,
// workerId: 1, // 工作节点 ID
// sequence: 42 // 序列号
// }
```
### 验证 ID
#### `isValid(id, strictWorkerId?)`
验证 ID 是否为有效的 Snowflake ID
**参数**
- `id` - 要验证的 ID(支持 Number、BigInt、String 类型)
- `strictWorkerId` - 可选,是否严格验证 workerId 必须匹配当前实例(默认:false)
**返回值**
- `boolean` - ID 是否有效
**验证规则**
- ✅ ID 为正数
- ✅ ID 在 64 位范围内
- ✅ 时间戳在合理范围内(>= baseTime,<= 当前时间 + 1秒容差)
- ✅ workerId 在有效范围内(0 到 2^workerIdBitLength-1)
- ✅ 序列号在有效范围内(0 到 2^seqBitLength-1)
- ✅ 严格模式下:workerId 必须匹配当前实例
```typescript
const genid = new GenidOptimized({ workerId: 1 })
const id = genid.nextId()
// 宽松模式:验证 ID 格式是否有效
genid.isValid(id) // true
genid.isValid(12345) // false(无效的 ID)
genid.isValid(-1) // false(负数)
genid.isValid('invalid') // false(无效格式)
// 严格模式:验证 ID 是否由当前实例生成
const genid2 = new GenidOptimized({ workerId: 2 })
const id2 = genid2.nextId()
genid.isValid(id2) // true(宽松模式,其他实例的 ID 也有效)
genid.isValid(id2, true) // false(严格模式,workerId 不匹配)
genid.isValid(id, true) // true(严格模式,workerId 匹配)
```
### 统计与配置
#### `getStats()`
获取生成器统计信息
```typescript
const stats = genid.getStats()
// {
// totalGenerated: 1000, // 总生成数量
// overCostCount: 10, // 漂移次数
// turnBackCount: 2, // 时钟回拨次数
// uptimeMs: 60000, // 运行时间
// avgPerSecond: 16, // 每秒平均生成量
// currentState: 'NORMAL' // 当前状态
// 获取运行统计
genid.getStats()
// => {
// totalGenerated: 1000,
// overCostCount: 10,
// turnBackCount: 2,
// uptimeMs: 60000,
// avgPerSecond: 16,
// currentState: 'NORMAL' | 'OVER_COST'
// }
```
#### `getConfig()`
获取配置信息
```typescript
const config = genid.getConfig()
// {
// 获取当前配置
genid.getConfig()
// => {
// method: 'DRIFT',

@@ -227,2 +112,3 @@ // workerId: 1,

// sequenceRange: '5-63',
// maxSequence: 63,
// idsPerMillisecond: 59,

@@ -234,20 +120,11 @@ // baseTime: Date,

// }
```
#### `resetStats()`
重置统计数据
```typescript
// 重置统计
genid.resetStats()
```
### 调试工具
### 调试
#### `formatBinary(id)`
格式化 ID 为二进制字符串
```typescript
console.log(genid.formatBinary(id))
genid.formatBinary(id)
// ID: 123456789012345

@@ -262,19 +139,7 @@ // Binary (64-bit):

### 基础用法
### 自定义位分配
```typescript
const genid = new GenidOptimized({
workerId: 1
})
import { GenidOptimized, GenidMethod } from '@cdlab996/genid'
// 生成单个 ID
const id1 = genid.nextId()
// 批量生成
const ids = genid.nextBatch(1000)
```
### 自定义配置
```typescript
const genid = new GenidOptimized({

@@ -284,40 +149,28 @@ workerId: 1,

baseTime: new Date('2024-01-01').valueOf(),
workerIdBitLength: 10, // 支持 1024 个节点
seqBitLength: 12, // 每毫秒 4096 个 ID
topOverCostCount: 5000
workerIdBitLength: 10, // 支持 1024 个节点
seqBitLength: 12, // 每毫秒 4096 个 ID
topOverCostCount: 5000,
})
```
### 验证 ID
### 验证外部 ID
```typescript
const genid = new GenidOptimized({ workerId: 1 })
// 生成并验证 ID
const id = genid.nextId()
if (genid.isValid(id)) {
console.log('ID 有效')
}
// 验证外部 ID(例如从数据库或 API 获取的 ID)
// 验证从数据库或 API 获取的 ID
const externalId = '123456789012345'
if (genid.isValid(externalId)) {
const info = genid.parse(externalId)
console.log('ID 有效,解析结果:', info)
console.log('生成时间:', info.timestamp)
console.log('来自节点:', info.workerId)
} else {
console.error('ID 无效')
console.error('无效 ID')
}
// 严格验证(只接受当前实例生成的 ID)
const isMyId = genid.isValid(id, true)
```
### 监控性能
### 性能监控
```typescript
// 定期检查统计信息
setInterval(() => {
const stats = genid.getStats()
console.log(`生成速率: ${stats.avgPerSecond} ID/秒`)
console.log(`漂移次数: ${stats.overCostCount}`)
console.log(`速率: ${stats.avgPerSecond} ID/s | 漂移: ${stats.overCostCount} | 回拨: ${stats.turnBackCount}`)
}, 10000)

@@ -328,33 +181,77 @@ ```

### DRIFT(漂移模式,推荐)
| 模式 | 说明 | 适用场景 |
| ----------------- | ---------------------------------------- | -------------------- |
| **DRIFT**(默认) | 序列号耗尽时借用未来时间戳,避免等待 | 高频 ID 生成、高并发 |
| **TRADITIONAL** | 严格按时间戳递增,序列号耗尽等待下一毫秒 | 对时间顺序严格要求 |
- 高并发下性能更好
- 允许时间戳漂移以避免等待
- 适合高频 ID 生成场景
## 架构
### TRADITIONAL(传统模式)
### ID 结构(64-bit)
- 严格按时间戳递增
- 序列号耗尽时等待下一毫秒
- 适合对时间顺序要求严格的场景
```
|------------ 时间戳 ------------|-- 工作节点 ID --|-- 序列号 --|
42-52 bits 1-15 bits 3-21 bits
```
默认配置:时间戳 52 bits(约 139 年)| 节点 ID 6 bits(64 个节点)| 序列号 6 bits(每毫秒 59 个 ID)
序列号 `0-4` 保留用于时钟回拨,正常使用从 `5` 开始。
### 核心流程
```mermaid
graph TB
A[开始生成 ID] --> B{是否处于漂移状态?}
B -->|否| C[正常路径]
B -->|是| D[漂移路径]
C --> E{检测时钟}
E -->|时钟回拨| F[使用保留序列号 0-4]
E -->|时间前进| G[重置序列号]
E -->|同一毫秒| H{序列号是否溢出?}
H -->|否| I[序列号+1 正常生成]
H -->|是| J[进入漂移状态 时间戳+1]
D --> K{检测时间}
K -->|时间追上| L[退出漂移 恢复正常]
K -->|超过最大漂移| M[等待下一毫秒 退出漂移]
K -->|继续漂移| N{序列号是否溢出?}
N -->|否| O[使用当前序列号]
N -->|是| P[时间戳+1 重置序列号]
F --> Q[计算 ID]
G --> Q
I --> Q
J --> Q
L --> Q
M --> Q
O --> Q
P --> Q
Q --> R[更新统计]
R --> S[返回 ID]
```
## 注意事项
⚠️ **重要提示**
- 每个 Worker/进程必须使用**不同的 workerId**
- 实例**不是线程安全的**,不要跨线程共享
- 实例**非线程安全**,不要跨线程共享
- `workerIdBitLength + seqBitLength` 不能超过 22
- 序列号 0-4 保留用于时钟回拨处理
- JavaScript 安全整数范围:`-(2^53-1)` 到 `2^53-1`
- 超出 JavaScript 安全整数范围(2^53-1)时,使用 `nextBigId()` 或 `nextId()`(自动返回 BigInt)
## 性能指标
## 性能
- 单实例吞吐量:> 50,000 ID/秒
- 默认配置下每毫秒可生成:59 个唯一 ID
- 支持的最大节点数:2^workerIdBitLength(默认 64 个)
- 时间戳可用时长:约 139 年(52 bits,从 baseTime 起算)
| 指标 | 数值 |
| -------------------------- | ------------- |
| 单实例吞吐量 | > 50,000 ID/s |
| 每毫秒生成量(默认配置) | 59 个 |
| 最大节点数(默认配置) | 64 个 |
| 时间戳可用时长(默认配置) | ~139 年 |
## 📜 License
## License
[MIT](./LICENSE) License © 2025-PRESENT [wudi](https://github.com/WuChenDi)