flake-idgen
Flake ID 生成器在分布式环境中生成 k 序、无冲突的 ID。
安装
npm install --save flake-idgen
| Timestamp | Datacenter | Worker | Counter | Flake ID |
| 0x8c20543b0 | 00000b | 00000b | 0x000 | 0x02308150ec000000 |
| 0x8c20543b1 | 00000b | 00000b | 0x000 | 0x02308150ec400000 |
| 0x8c20543b1 | 00000b | 00000b | 0x001 | 0x02308150ec400001 |
| 0x8c20543b1 | 00000b | 00000b | 0x002 | 0x02308150ec400002 |
| 0x8c20543b1 | 00000b | 00000b | 0x003 | 0x02308150ec400003 |
| 0x8c20c0335 | 00011b | 00001b | 0x000 | 0x02308300cd461000 |
| 0x8c20c0335 | 00011b | 00001b | 0x001 | 0x02308300cd461001 |
每个 Flake ID 都是 64 位长,包括:
timestamp, 自 1970 年 1 月 1 日 00:00:00 UTC 起经过的 42 位长毫秒数
datacenter,一个 5 位长的数据中心标识符。它最多可以包含 32 个唯一值(包括 0)
worker,一个 5 位长的工人标识符。它最多可以包含 32 个唯一值(包括 0)
counter,一个 12 位长的 id 计数器,在同一毫秒内。它最多可以包含 4096 个唯一值。
id 的位细分,例如 5828128208445124608(计数器是 0,数据中心是 7 和工作人员 3)如下:
010100001110000110101011101110100001000111 00111 00011 000000000000
|------------| 12 bit counter
|-----| 5 bit worker
|-----| 5 bit datacenter
|----- -----| 10 bit generator identifier
|------------------------------------------| 42 bit timestamp
请注意,由 datacenter id 和 worker id 组成 1024 个唯一的生成器标识符。通过修改 datacenter 和 worker id,我们可以在一台机器上获得多达 1024 个 id 生成器(例如,每个都在一个单独的进程中运行),或者有 1024 台机器上每个都有一个 id 生成器。也可以提供一个 10 位长的标识符(最多 1024 个值)。该 id 在内部分为 datacenter(最重要的 5 位)和 worker(最不重要的 5 位)。
用法
Flake ID Generator 返回 8 字节长的节点缓冲区对象,其字节代表 64 位长 id。请注意,数字以大端格式存储,即数字的最高有效字节存储在给定的最小地址中,最低有效字节存储在最大地址中。
Flake id 生成器实例有一种方法 next(cb)返回生成的 id(如果未提供回调函数)或使用两个参数调用提供的回调函数:error 和 generated id。
以下示例使用 next 没有回调函数:
var FlakeId = require('flake-idgen');
var flakeIdGen = new FlakeId();
console.log(flakeIdGen.next()); //
console.log(flakeIdGen.next()); //
console.log(flakeIdGen.next()); //
与回调函数一起使用:
var FlakeId = require('flake-idgen');
var flakeIdGen = new FlakeId();
flakeIdGen.next(function (err, id) {
console.info(id); //
})
flakeIdGen.next(function (err, id) {
console.info(id); //
})
Flake ID Generator 可以在一毫秒内生成多达 4096 个唯一标识符。当生成器试图在一毫秒内生成超过 4096 个标识符时,会发生以下事情:
在 next()没有回调函数的情况下使用时,会抛出错误。
next(cb)与回调函数一起使用时,回调函数在接下来的毫秒内被调用,没有任何错误。
额外的发电机设置参数
Flake Id 生成器构造函数采用具有以下属性的可选参数(生成器配置选项):
datacenter(5 位)- 数据中心标识符。它的值可以是 0 到 31。
worker(5 位)- 工人标识符。它的值可以是 0 到 31。
id(10 位) - 发电机标识符。它可以具有从 0 到 1023 的值。可以提供它来代替 datacenter 和 worker 标识符。
epoch- 用于减少生成的时间戳值的数字。请注意,此数字不应超过自 1970 年 1 月 1 日 00:00:00 UTC 以来经过的毫秒数。它可用于生成较小的 id。
使用 datacenter 和 worker 标识符的示例:
var FlakeId = require('flake-idgen')
var flakeIdGen1 = new FlakeId();
var flakeIdGen2 = new FlakeId({ datacenter: 9, worker: 7 });
console.info(flakeIdGen1.next()); //
console.info(flakeIdGen2.next()); //
epoch 参数示例:
var FlakeId = require('flake-idgen')
var flakeIdGen1 = new FlakeId();
var flakeIdGen2 = new FlakeId({ epoch: 1300000000000 });
console.info(flakeIdGen1.next()); //
console.info(flakeIdGen2.next()); //
Flake Id 生成器有一些可以从生成器实例中读取的属性:
datacenter- 返回用于生成器创建的工人编号;否则返回 undefined 值。
worker- 返回用于生成器创建的工人编号;否则返回 undefined 值。
id- 返回用于生成器创建的工人标识符号或将其值从数据中心和工人号组合。标识符始终可用,默认为零。
Flake Id 生成器在没有任何参数的情况下实例化 datacenter,worker 并且 id 值默认为零。
var FlakeId = require('flake-idgen')
var flakeIdGen1 = new FlakeId({ id: 100 });
var flakeIdGen2 = new FlakeId({ datacenter: 9, worker: 7 });
var flakeIdGen3 = new FlakeId();
console.info(flakeIdGen1.id); // 100
console.info(flakeIdGen1.datacenter); // undefined
console.info(flakeIdGen1.worker); // undefined
console.info(flakeIdGen2.datacenter); // 9
console.info(flakeIdGen2.worker); // 7
console.info(flakeIdGen2.id); // 259
console.info(flakeIdGen3.datacenter); // 0
console.info(flakeIdGen3.worker); // 0
console.info(flakeIdGen3.id); // 0
有时 Node.js 时钟可能会倒退。在大多数情况下,它只有几毫秒。但是,由于生成器依赖于当前时间戳,因此在时钟赶上最后一个时间戳值之前,它将无法生成无冲突标识符(即没有重复)。如果时钟向后移动,将发生以下情况:
在 next()没有回调函数的情况下使用时,会抛出错误。
当 next(cb)与回调函数一起使用时,一旦时钟赶上最后一个时间戳,就会使用生成的新标识符调用回调函数。
格式化方法
npm install --save biguint-format
Flake Id 生成器返回代表 64 位数字的节点缓冲区,以便将来扩展或返回缓冲区修改。Node Buffer 也可以很容易地转换为字符串格式。有一个 NPM biguint-format 模块,它提供缓冲区到字符串的转换功能,例如
var intformat = require('biguint-format')
, FlakeId = require('flake-idgen')
var flakeIdGen1 = new FlakeId();
var flakeIdGen2 = new FlakeId({ epoch: 1300000000000 });
console.info(intformat(flakeIdGen1.next(), 'dec')); // 5827056208820830208
console.info(intformat(flakeIdGen1.next(), 'hex', { prefix: '0x' })); // 0x50dddcbfb5c00001
console.info(intformat(flakeIdGen2.next(), 'dec')); // 374461008833413120
console.info(intformat(flakeIdGen2.next(), 'hex', { prefix: '0x' })); // 0x5325a4db6000002