Neat Paraskavedekatriaphobia's Meaning

    snowflakeid-ro

    1.0.0 • Public • Published

    Snowflake id 生成器

    • 2017-03-14 1.0.4 增加human readable格式转换支持, toHumanReadable(), fromHumanReadable()

    关于Snowflake id

    基本思想源于twitter的Snowflake方案,该实现可提供高性能、低延迟、高可用的ID生成。

    每个ID是一个long类型的整数,结构如下:

    0     A     41    B     51    C   54  D  63
    +-----------+-----------+---------+--------+
    | timestamp |   hw id   | shardId | seq Id |
    +-----------+-----------+---------+--------+
    
    • A. 前41位是timestamp,精确到千分之一秒,即mS。这样可以使ID生成变得有序。
    • B. 10位HW ID(表示主机或者docker),这样可以有1024个节点, HwID由MAC地址最后7位+本实例进程号最后3位组成。
    • C. 3位分片id, 最大支持8个分片
    • D. 最后10位为了解决并发冲突问题,并发请求时以此10位作累加,这样在同一个毫秒最多可以生成1024个ID。

    通过以上方案,可以快速生成时间有序的,带节点标识的ID。基于这个思想,我们可以做各种变形以满足自身需要,比如可以调整四部分的顺序和每一部分的位数以满足具体场景;可以开启多个进程,每个进程负责某些node节点的ID生成以避免单点;可以精简位数,并做编码转换以减少ID长度等等。

    设计思路

    这个方案与其它snowflake id生成器不同的地方有:

    1. 直接使用第0位,不再留空。所以需要在DB Schema中定义存储的字段为BIGINT UNSIGNED
    CREATE TABLE test(
        id    BIGINT UNSIGNED,
    );
    1. 采用了3位shardId,用以数据表分片扩展用途。
    2. 10位HwID用以标识各主机或者容器(MAC最后7位+进程ID后3位)
    3. 采用singleton模式设计

    Human-readable

    让sfid变得可以阅读的解决思路:

    0 - 00000 1 - 00001 2 - 00010 3 - 00011

    4 - 00100 5 - 00101 6 - 00110 7 - 00111

    8 - 01000 9 - 01001 A - 01010 B - 01011

    C - 01100 D - 01101 E - 01110 F - 01111

    G - 10000 H - 10001 I - 与L、1相似,略去

    J - 10010 K - 10011 L - 与I、1相似,略去

    M - 10100 N - 10101 O - 与0相似,略去

    P - 10110 Q - 10111 R - 11000 S - 与5相似,略去

    T - 11001 U - 11010 V - 11011 W - 11100

    X - 11101 Y - 11110 Z - 11111

    所以64位的SFID整形数,可以用64/5=12余4,一共13个符号既可以表示出来。可以用“012-34567-89ABC”的格式呈现优惠码,会员号等在系统用sfid表示的数据

    12491575082415873361 = 1010 11010 10110 10111 11101 01011 01010 11000 01000 01001 10111 01010 10001 = AUP-QXBAR-89QAH

    12491570832403129941 = 1010 11010 10110 10111 11001 01111 10100 10100 00000 01001 11001 10010 10101 = AUP-QTFMM-09TJN

    12491566990856848639 = 1010 11010 10110 10111 10101 11111 11010 11101 00000 01001 00001 00111 11111 = AUP-QNZUX-0917Z

    使用方法

    1. callback方式
    var snowflake = require('snowflakeid-ro');
    snowflake.getSnowflakeIDFactory(function(err, idGen) {
        idGen.next();                           // 生成一个id
        var idString = idGen.toString();
        console.log(idGen.toString());          // 按照10进制输出显示
        console.log(idGen.toString(16));        // 按照16进制输出显示
        
        var timestamp = idGen.getTimestamp(idString);  // timestamp = 1475143031137
        var hwid = idGen.getHwId(idString);    // hwid = 0x3f
        var shardId = idGen.getShardId(idString); // shardId = 0x0
        var seqId = idGen.getSeqId(idString); // seqId = 123
    });
    1. 或者promise方式
    var snowflake = require('snowflakeid-romens');
    snowflake.getSnowflakeIDPromise()
             .then(function(sid){
                 ...
             })
             .catch(function(err){
                 ...
             });
    
    1. 转换为32进制显示
    var snowflake = require('snowflakeid-ro');
    var hrStr = snowflake.toHumanReadable("12491575082415873361");
    console.log(hrStr); // AUP-QXBAR-89QAH
    console.log(snowflake.fromHumanReadable(hrStr).toString(10)); // 12491575082415873361

    Install

    npm i snowflakeid-ro

    DownloadsWeekly Downloads

    1

    Version

    1.0.0

    License

    none

    Unpacked Size

    15.8 kB

    Total Files

    7

    Last publish

    Collaborators

    • avatar