首先必须要修改默认的 /config/config.js
,内容如下;
{
worker_id: -1,
datacenter_id: -1
}
worker_id 是 0-31
的机器ID(用来配置分布式的多机器,最多支持32个机器)
datacenter_id 是 0-31
的数据ID(用来配置某个机器下面的某某服务,每台机器最多支持32个服务)
之所以需要手动配置,是防止使用者误操作(没有做配置,会报错提醒你设置);
配置完以后,如下操作,返回是Bigint类型的ID
var idWorker = require("../index");
let id = idWorker.nextId();//45386714578944n
关于Bigint类型的说明,请参考:https://www.axihe.com/api/js-es/ob-bigint/overview.html
网上搜到的方案基本是按照推特的方案(10位的数据机器位分成 5位机器ID + 5位数据ID ),目前代码按照这个方案来做的;
方案的实现参考:https://github.com/twitter-archive/snowflake
Twitter_Snowflake
SnowFlake的结构如下(每部分用-分开):
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
A-|--------------------B--------------------------|-------C-------|------D------|
-
A区:1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
-
B区:41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)得到的值, 这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,
(1n << 41n) / (1000n * 60n * 60n * 24n * 365n) = 69n
-
C区:10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId(2^52^5 = 1024)
-
D区:12位序列,毫秒内的计数,12位 的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号(2^12=4096)
加起来刚好64位,为一个Long型。
SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据ID和机器ID作区分),并且效率较高。
理论1S内生成的ID数量是 1000*4096 = 4096000(四百零九万六千个)
代码中使用Bigint实现,该类型在 Node10.X 版本才开始支持
生成100W条ID, 时间约 640-660ms
生成409.6WW条ID, 时间约约 2600-2800ms
具体可以自己跑下本项目的test文件