@cdlab996/genid 1.2.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,73 +1,28 @@
1
1
  # @cdlab996/genid
2
2
 
3
- 基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理,适用于分布式系统中的唯一标识生成需求。
3
+ [![npm version](https://img.shields.io/npm/v/@cdlab996/genid)](https://www.npmjs.com/package/@cdlab996/genid)
4
+ [![license](https://img.shields.io/npm/l/@cdlab996/genid)](./LICENSE)
5
+
6
+ 基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理。
4
7
 
5
8
  ## 特性
6
9
 
7
- - 🚀 **漂移算法**:高并发场景下性能优异
8
- - 🔄 **时钟回拨处理**:优雅处理时钟回拨,不阻塞 ID 生成
9
- - ⚙️ **灵活配置**:支持自定义位长度分配
10
- - 📊 **性能监控**:内置统计和调试功能
11
- - **ID 验证**:验证 ID 的有效性,支持严格/宽松模式
10
+ - **漂移算法** - 高并发场景下突破每毫秒序列号上限,性能更优
11
+ - **时钟回拨处理** - 使用保留序列号优雅降级,不阻塞 ID 生成
12
+ - **灵活配置** - 支持自定义时间戳、节点 ID、序列号的位长度分配
13
+ - **ID 验证** - 支持严格/宽松模式校验 ID 有效性
14
+ - **运行监控** - 内置统计、解析和二进制格式化调试工具
12
15
 
13
- ## 架构设计
16
+ ## 安装
14
17
 
15
- ### 核心流程
18
+ ```bash
19
+ # npm
20
+ npm install @cdlab996/genid
16
21
 
17
- ```mermaid
18
- graph TB
19
- A[开始生成 ID] --> B{是否处于漂移状态?}
20
-
21
- B -->|否| C[正常路径]
22
- B -->|是| D[漂移路径]
23
-
24
- C --> E{检测时钟}
25
- E -->|时钟回拨| F[使用保留序列号 0-4]
26
- E -->|时间前进| G[重置序列号]
27
- E -->|同一毫秒| H{序列号是否溢出?}
28
-
29
- H -->|否| I[序列号+1 正常生成]
30
- H -->|是| J[进入漂移状态 时间戳+1]
31
-
32
- D --> K{检测时间}
33
- K -->|时间追上| L[退出漂移 恢复正常]
34
- K -->|超过最大漂移| M[等待下一毫秒 退出漂移]
35
- K -->|继续漂移| N{序列号是否溢出?}
36
-
37
- N -->|否| O[使用当前序列号]
38
- N -->|是| P[时间戳+1 重置序列号]
39
-
40
- F --> Q[计算 ID]
41
- G --> Q
42
- I --> Q
43
- J --> Q
44
- L --> Q
45
- M --> Q
46
- O --> Q
47
- P --> Q
48
-
49
- Q --> R[更新统计]
50
- R --> S[返回 ID]
22
+ # pnpm
23
+ pnpm add @cdlab996/genid
51
24
  ```
52
25
 
53
- ### ID 结构(64-bit)
54
-
55
- ```
56
- |------------ 时间戳 ------------|-- 工作节点 ID --|-- 序列号 --|
57
- 42-52 bits 1-15 bits 3-21 bits
58
- ```
59
-
60
- **位分配示例(默认配置):**
61
-
62
- - 时间戳:52 bits(可用约 139 年)
63
- - 工作节点 ID:6 bits(支持 64 个节点)
64
- - 序列号:6 bits(每毫秒 59 个 ID,5-63)
65
-
66
- **序列号分配:**
67
-
68
- - `0-4`:保留用于时钟回拨
69
- - `5-maxSeqNumber`:正常使用
70
-
71
26
  ## 快速开始
72
27
 
73
28
  ```typescript
@@ -78,175 +33,97 @@ const genid = new GenidOptimized({ workerId: 1 })
78
33
 
79
34
  // 生成 ID
80
35
  const id = genid.nextId()
81
- console.log(id) // 123456789012345
82
- ```
83
-
84
- ## API 参考
85
-
86
- ### 构造函数
87
-
88
- ```typescript
89
- new GenidOptimized(options: GenidOptions)
90
- ```
91
-
92
- **配置选项**
93
-
94
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
95
- |------|------|------|--------|------|
96
- | `workerId` | number | ✅ | - | 工作节点 ID(范围:0 到 2^workerIdBitLength-1) |
97
- | `method` | GenidMethod | ❌ | `DRIFT` | 算法类型:`DRIFT` 或 `TRADITIONAL` |
98
- | `baseTime` | number | ❌ | `1577836800000` | 起始时间戳(毫秒,默认:2020-01-01) |
99
- | `workerIdBitLength` | number | ❌ | `6` | 工作节点 ID 位数(1-15) |
100
- | `seqBitLength` | number | ❌ | `6` | 序列号位数(3-21) |
101
- | `maxSeqNumber` | number | ❌ | `2^seqBitLength-1` | 最大序列号 |
102
- | `minSeqNumber` | number | ❌ | `5` | 最小序列号(0-4 保留用于时钟回拨) |
103
- | `topOverCostCount` | number | ❌ | `2000` | 最大漂移次数 |
104
-
105
- ### 生成 ID
106
-
107
- #### `nextId()`
108
-
109
- 返回 Number 或 BigInt 类型的 ID(自动选择)
110
-
111
- ```typescript
112
- const id = genid.nextId()
113
- ```
114
-
115
- #### `nextNumber()`
116
-
117
- 返回 Number 类型的 ID(超出安全范围会抛出错误)
118
36
 
119
- ```typescript
120
- const id = genid.nextNumber()
121
- ```
122
-
123
- #### `nextBigId()`
37
+ // 批量生成
38
+ const ids = genid.nextBatch(1000)
124
39
 
125
- 返回 BigInt 类型的 ID
40
+ // 解析 ID
41
+ const info = genid.parse(id)
42
+ // => { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
126
43
 
127
- ```typescript
128
- const id = genid.nextBigId()
44
+ // 验证 ID
45
+ genid.isValid(id) // true
129
46
  ```
130
47
 
131
- #### `nextBatch(count, asBigInt?)`
48
+ ## API
132
49
 
133
- 批量生成 ID
50
+ ### `new GenidOptimized(options)`
134
51
 
135
- ```typescript
136
- const ids = genid.nextBatch(100) // 生成 100 ID
137
- const bigIds = genid.nextBatch(100, true) // 生成 100 个 BigInt ID
138
- ```
52
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
53
+ | ------------------- | ------------- | :---: | ------------------ | --------------------------------------------- |
54
+ | `workerId` | `number` | Yes | - | 工作节点 ID(0 ~ 2^workerIdBitLength-1) |
55
+ | `method` | `GenidMethod` | | `DRIFT` | 算法:`DRIFT`(漂移)或 `TRADITIONAL`(传统) |
56
+ | `baseTime` | `number` | | `1577836800000` | 起始时间戳,毫秒(默认 2020-01-01) |
57
+ | `workerIdBitLength` | `number` | | `6` | 节点 ID 位数(1-15) |
58
+ | `seqBitLength` | `number` | | `6` | 序列号位数(3-21) |
59
+ | `maxSeqNumber` | `number` | | `2^seqBitLength-1` | 最大序列号 |
60
+ | `minSeqNumber` | `number` | | `5` | 最小序列号(0-4 保留用于时钟回拨) |
61
+ | `topOverCostCount` | `number` | | `2000` | 最大漂移次数 |
139
62
 
140
- ### 解析 ID
141
-
142
- #### `parse(id)`
143
-
144
- 解析 ID,提取组成部分
63
+ ### 生成 ID
145
64
 
146
65
  ```typescript
147
- const info = genid.parse(id)
148
- console.log(info)
149
- // {
150
- // timestamp: Date, // 生成时间
151
- // timestampMs: 1609459200000,
152
- // workerId: 1, // 工作节点 ID
153
- // sequence: 42 // 序列号
154
- // }
66
+ genid.nextId() // 返回 number | bigint(自动选择)
67
+ genid.nextNumber() // 返回 number(超出安全整数范围抛错)
68
+ genid.nextBigId() // 返回 bigint
69
+ genid.nextBatch(100) // 批量生成 100 个 ID
70
+ genid.nextBatch(100, true) // 批量生成 100 个 BigInt ID
155
71
  ```
156
72
 
157
- ### 验证 ID
158
-
159
- #### `isValid(id, strictWorkerId?)`
160
-
161
- 验证 ID 是否为有效的 Snowflake ID
162
-
163
- **参数**
164
- - `id` - 要验证的 ID(支持 Number、BigInt、String 类型)
165
- - `strictWorkerId` - 可选,是否严格验证 workerId 必须匹配当前实例(默认:false)
166
-
167
- **返回值**
168
- - `boolean` - ID 是否有效
169
-
170
- **验证规则**
171
- - ✅ ID 为正数
172
- - ✅ ID 在 64 位范围内
173
- - ✅ 时间戳在合理范围内(>= baseTime,<= 当前时间 + 1秒容差)
174
- - ✅ workerId 在有效范围内(0 到 2^workerIdBitLength-1)
175
- - ✅ 序列号在有效范围内(0 到 2^seqBitLength-1)
176
- - ✅ 严格模式下:workerId 必须匹配当前实例
73
+ ### 解析与验证
177
74
 
178
75
  ```typescript
179
- const genid = new GenidOptimized({ workerId: 1 })
180
- const id = genid.nextId()
181
-
182
- // 宽松模式:验证 ID 格式是否有效
183
- genid.isValid(id) // true
184
- genid.isValid(12345) // false(无效的 ID)
185
- genid.isValid(-1) // false(负数)
186
- genid.isValid('invalid') // false(无效格式)
76
+ // 解析 ID 的组成部分
77
+ genid.parse(id)
78
+ // => { timestamp: Date, timestampMs: number, workerId: number, sequence: number }
187
79
 
188
- // 严格模式:验证 ID 是否由当前实例生成
189
- const genid2 = new GenidOptimized({ workerId: 2 })
190
- const id2 = genid2.nextId()
80
+ // 宽松验证:检查 ID 格式是否有效
81
+ genid.isValid(id) // true
82
+ genid.isValid(12345) // false
83
+ genid.isValid('invalid') // false
191
84
 
192
- genid.isValid(id2) // true(宽松模式,其他实例的 ID 也有效)
193
- genid.isValid(id2, true) // false(严格模式,workerId 不匹配)
194
- genid.isValid(id, true) // true(严格模式,workerId 匹配)
85
+ // 严格验证:要求 workerId 匹配当前实例
86
+ genid.isValid(id, true) // true(本实例生成的 ID)
87
+ genid.isValid(otherId, true) // false(其他实例生成的 ID)
195
88
  ```
196
89
 
197
90
  ### 统计与配置
198
91
 
199
- #### `getStats()`
200
-
201
- 获取生成器统计信息
202
-
203
92
  ```typescript
204
- const stats = genid.getStats()
205
- // {
206
- // totalGenerated: 1000, // 总生成数量
207
- // overCostCount: 10, // 漂移次数
208
- // turnBackCount: 2, // 时钟回拨次数
209
- // uptimeMs: 60000, // 运行时间
210
- // avgPerSecond: 16, // 每秒平均生成量
211
- // currentState: 'NORMAL' // 当前状态
93
+ // 获取运行统计
94
+ genid.getStats()
95
+ // => {
96
+ // totalGenerated: 1000,
97
+ // overCostCount: 10,
98
+ // turnBackCount: 2,
99
+ // uptimeMs: 60000,
100
+ // avgPerSecond: 16,
101
+ // currentState: 'NORMAL' | 'OVER_COST'
212
102
  // }
213
- ```
214
-
215
- #### `getConfig()`
216
-
217
- 获取配置信息
218
103
 
219
- ```typescript
220
- const config = genid.getConfig()
221
- // {
104
+ // 获取当前配置
105
+ genid.getConfig()
106
+ // => {
222
107
  // method: 'DRIFT',
223
108
  // workerId: 1,
224
109
  // workerIdRange: '0-63',
225
110
  // sequenceRange: '5-63',
111
+ // maxSequence: 63,
226
112
  // idsPerMillisecond: 59,
227
113
  // baseTime: Date,
228
114
  // timestampBits: 52,
229
115
  // workerIdBits: 6,
230
116
  // sequenceBits: 6
231
117
  // }
232
- ```
233
-
234
- #### `resetStats()`
235
118
 
236
- 重置统计数据
237
-
238
- ```typescript
119
+ // 重置统计
239
120
  genid.resetStats()
240
121
  ```
241
122
 
242
- ### 调试工具
243
-
244
- #### `formatBinary(id)`
245
-
246
- 格式化 ID 为二进制字符串
123
+ ### 调试
247
124
 
248
125
  ```typescript
249
- console.log(genid.formatBinary(id))
126
+ genid.formatBinary(id)
250
127
  // ID: 123456789012345
251
128
  // Binary (64-bit):
252
129
  // 0000000000011010... - 时间戳 (52 bits) = 2025-10-17T...
@@ -256,99 +133,119 @@ console.log(genid.formatBinary(id))
256
133
 
257
134
  ## 使用示例
258
135
 
259
- ### 基础用法
136
+ ### 自定义位分配
260
137
 
261
138
  ```typescript
262
- const genid = new GenidOptimized({
263
- workerId: 1
264
- })
139
+ import { GenidOptimized, GenidMethod } from '@cdlab996/genid'
265
140
 
266
- // 生成单个 ID
267
- const id1 = genid.nextId()
268
-
269
- // 批量生成
270
- const ids = genid.nextBatch(1000)
271
- ```
272
-
273
- ### 自定义配置
274
-
275
- ```typescript
276
141
  const genid = new GenidOptimized({
277
142
  workerId: 1,
278
143
  method: GenidMethod.TRADITIONAL,
279
144
  baseTime: new Date('2024-01-01').valueOf(),
280
- workerIdBitLength: 10, // 支持 1024 个节点
281
- seqBitLength: 12, // 每毫秒 4096 个 ID
282
- topOverCostCount: 5000
145
+ workerIdBitLength: 10, // 支持 1024 个节点
146
+ seqBitLength: 12, // 每毫秒 4096 个 ID
147
+ topOverCostCount: 5000,
283
148
  })
284
149
  ```
285
150
 
286
- ### 验证 ID
151
+ ### 验证外部 ID
287
152
 
288
153
  ```typescript
289
- const genid = new GenidOptimized({ workerId: 1 })
290
-
291
- // 生成并验证 ID
292
- const id = genid.nextId()
293
- if (genid.isValid(id)) {
294
- console.log('ID 有效')
295
- }
296
-
297
- // 验证外部 ID(例如从数据库或 API 获取的 ID)
154
+ // 验证从数据库或 API 获取的 ID
298
155
  const externalId = '123456789012345'
299
156
  if (genid.isValid(externalId)) {
300
157
  const info = genid.parse(externalId)
301
- console.log('ID 有效,解析结果:', info)
158
+ console.log('生成时间:', info.timestamp)
159
+ console.log('来自节点:', info.workerId)
302
160
  } else {
303
- console.error('ID 无效')
161
+ console.error('无效 ID')
304
162
  }
305
-
306
- // 严格验证(只接受当前实例生成的 ID)
307
- const isMyId = genid.isValid(id, true)
308
163
  ```
309
164
 
310
- ### 监控性能
165
+ ### 性能监控
311
166
 
312
167
  ```typescript
313
- // 定期检查统计信息
314
168
  setInterval(() => {
315
169
  const stats = genid.getStats()
316
- console.log(`生成速率: ${stats.avgPerSecond} ID/秒`)
317
- console.log(`漂移次数: ${stats.overCostCount}`)
170
+ console.log(`速率: ${stats.avgPerSecond} ID/s | 漂移: ${stats.overCostCount} | 回拨: ${stats.turnBackCount}`)
318
171
  }, 10000)
319
172
  ```
320
173
 
321
174
  ## 算法模式
322
175
 
323
- ### DRIFT(漂移模式,推荐)
176
+ | 模式 | 说明 | 适用场景 |
177
+ | ----------------- | ---------------------------------------- | -------------------- |
178
+ | **DRIFT**(默认) | 序列号耗尽时借用未来时间戳,避免等待 | 高频 ID 生成、高并发 |
179
+ | **TRADITIONAL** | 严格按时间戳递增,序列号耗尽等待下一毫秒 | 对时间顺序严格要求 |
324
180
 
325
- - 高并发下性能更好
326
- - 允许时间戳漂移以避免等待
327
- - 适合高频 ID 生成场景
181
+ ## 架构
328
182
 
329
- ### TRADITIONAL(传统模式)
183
+ ### ID 结构(64-bit)
330
184
 
331
- - 严格按时间戳递增
332
- - 序列号耗尽时等待下一毫秒
333
- - 适合对时间顺序要求严格的场景
185
+ ```
186
+ |------------ 时间戳 ------------|-- 工作节点 ID --|-- 序列号 --|
187
+ 42-52 bits 1-15 bits 3-21 bits
188
+ ```
334
189
 
335
- ## 注意事项
190
+ 默认配置:时间戳 52 bits(约 139 年)| 节点 ID 6 bits(64 个节点)| 序列号 6 bits(每毫秒 59 个 ID)
336
191
 
337
- ⚠️ **重要提示**
192
+ 序列号 `0-4` 保留用于时钟回拨,正常使用从 `5` 开始。
193
+
194
+ ### 核心流程
195
+
196
+ ```mermaid
197
+ graph TB
198
+ A[开始生成 ID] --> B{是否处于漂移状态?}
199
+
200
+ B -->|否| C[正常路径]
201
+ B -->|是| D[漂移路径]
202
+
203
+ C --> E{检测时钟}
204
+ E -->|时钟回拨| F[使用保留序列号 0-4]
205
+ E -->|时间前进| G[重置序列号]
206
+ E -->|同一毫秒| H{序列号是否溢出?}
207
+
208
+ H -->|否| I[序列号+1 正常生成]
209
+ H -->|是| J[进入漂移状态 时间戳+1]
210
+
211
+ D --> K{检测时间}
212
+ K -->|时间追上| L[退出漂移 恢复正常]
213
+ K -->|超过最大漂移| M[等待下一毫秒 退出漂移]
214
+ K -->|继续漂移| N{序列号是否溢出?}
215
+
216
+ N -->|否| O[使用当前序列号]
217
+ N -->|是| P[时间戳+1 重置序列号]
218
+
219
+ F --> Q[计算 ID]
220
+ G --> Q
221
+ I --> Q
222
+ J --> Q
223
+ L --> Q
224
+ M --> Q
225
+ O --> Q
226
+ P --> Q
227
+
228
+ Q --> R[更新统计]
229
+ R --> S[返回 ID]
230
+ ```
231
+
232
+ ## 注意事项
338
233
 
339
234
  - 每个 Worker/进程必须使用**不同的 workerId**
340
- - 实例**不是线程安全的**,不要跨线程共享
235
+ - 实例**非线程安全**,不要跨线程共享
341
236
  - `workerIdBitLength + seqBitLength` 不能超过 22
342
237
  - 序列号 0-4 保留用于时钟回拨处理
343
- - JavaScript 安全整数范围:`-(2^53-1)` `2^53-1`
238
+ - 超出 JavaScript 安全整数范围(2^53-1)时,使用 `nextBigId()` `nextId()`(自动返回 BigInt)
344
239
 
345
- ## 性能指标
240
+ ## 性能
346
241
 
347
- - 单实例吞吐量:> 50,000 ID/秒
348
- - 默认配置下每毫秒可生成:59 个唯一 ID
349
- - 支持的最大节点数:2^workerIdBitLength(默认 64 个)
350
- - 时间戳可用时长:约 139 年(52 bits,从 baseTime 起算)
242
+ | 指标 | 数值 |
243
+ | -------------------------- | ------------- |
244
+ | 单实例吞吐量 | > 50,000 ID/s |
245
+ | 每毫秒生成量(默认配置) | 59 个 |
246
+ | 最大节点数(默认配置) | 64 个 |
247
+ | 时间戳可用时长(默认配置) | ~139 年 |
351
248
 
352
- ## 📜 License
249
+ ## License
353
250
 
354
251
  [MIT](./LICENSE) License © 2025-PRESENT [wudi](https://github.com/WuChenDi)