2013-10-10 50 views
0

我需要在我的服務器端代碼以及客戶端代碼(在瀏覽器中)上創建UID。我目前使用NewID()作爲我的默認值,但是當創建客戶端(在瀏覽器中)時,我使用uuid.js.我更可能與NewSequentialId()發生衝突作爲我的默認值(在服務器端創建對象時使用)?NewId vs NewSequentialId與其他uuid源碼結合使用(javascript)

僅供參考這裏是uuid.js代碼,因爲我不記得我在哪裏下載它。

//  uuid.js 
// 
//  Copyright (c) 2010-2012 Robert Kieffer 
//  MIT License - http://opensource.org/licenses/mit-license.php 

(function() { 
    var _global = this; 

    // Unique ID creation requires a high quality random # generator. We feature 
    // detect to determine the best RNG source, normalizing to a function that 
    // returns 128-bits of randomness, since that's what's usually required 
    var _rng; 

    // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html 
    // 
    // Moderately fast, high quality 
    if (typeof(require) == 'function') { 
    try { 
     var _rb = require('crypto').randomBytes; 
     _rng = _rb && function() {return _rb(16);}; 
    } catch(e) {} 
    } 

    if (!_rng && _global.crypto && crypto.getRandomValues) { 
    // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto 
    // 
    // Moderately fast, high quality 
    var _rnds8 = new Uint8Array(16); 
    _rng = function whatwgRNG() { 
     crypto.getRandomValues(_rnds8); 
     return _rnds8; 
    }; 
    } 

    if (!_rng) { 
    // Math.random()-based (RNG) 
    // 
    // If all else fails, use Math.random(). It's fast, but is of unspecified 
    // quality. 
    var _rnds = new Array(16); 
    _rng = function() { 
     for (var i = 0, r; i < 16; i++) { 
     if ((i & 0x03) === 0) r = Math.random() * 0x100000000; 
     _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; 
     } 

     return _rnds; 
    }; 
    } 

    // Buffer class to use 
    var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array; 

    // Maps for number <-> hex string conversion 
    var _byteToHex = []; 
    var _hexToByte = {}; 
    for (var i = 0; i < 256; i++) { 
    _byteToHex[i] = (i + 0x100).toString(16).substr(1); 
    _hexToByte[_byteToHex[i]] = i; 
    } 

    // **`parse()` - Parse a UUID into it's component bytes** 
    function parse(s, buf, offset) { 
    var i = (buf && offset) || 0, ii = 0; 

    buf = buf || []; 
    s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { 
     if (ii < 16) { // Don't overflow! 
     buf[i + ii++] = _hexToByte[oct]; 
     } 
    }); 

    // Zero out remaining bytes if string was short 
    while (ii < 16) { 
     buf[i + ii++] = 0; 
    } 

    return buf; 
    } 

    // **`unparse()` - Convert UUID byte array (ala parse()) into a string** 
    function unparse(buf, offset) { 
    var i = offset || 0, bth = _byteToHex; 
    return bth[buf[i++]] + bth[buf[i++]] + 
      bth[buf[i++]] + bth[buf[i++]] + '-' + 
      bth[buf[i++]] + bth[buf[i++]] + '-' + 
      bth[buf[i++]] + bth[buf[i++]] + '-' + 
      bth[buf[i++]] + bth[buf[i++]] + '-' + 
      bth[buf[i++]] + bth[buf[i++]] + 
      bth[buf[i++]] + bth[buf[i++]] + 
      bth[buf[i++]] + bth[buf[i++]]; 
    } 

    // **`v1()` - Generate time-based UUID** 
    // 
    // Inspired by https://github.com/LiosK/UUID.js 
    // and http://docs.python.org/library/uuid.html 

    // random #'s we need to init node and clockseq 
    var _seedBytes = _rng(); 

    // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) 
    var _nodeId = [ 
    _seedBytes[0] | 0x01, 
    _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] 
    ]; 

    // Per 4.2.2, randomize (14 bit) clockseq 
    var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; 

    // Previous uuid creation time 
    var _lastMSecs = 0, _lastNSecs = 0; 

    // See https://github.com/broofa/node-uuid for API details 
    function v1(options, buf, offset) { 
    var i = buf && offset || 0; 
    var b = buf || []; 

    options = options || {}; 

    var clockseq = options.clockseq != null ? options.clockseq : _clockseq; 

    // UUID timestamps are 100 nano-second units since the Gregorian epoch, 
    // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so 
    // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' 
    // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. 
    var msecs = options.msecs != null ? options.msecs : new Date().getTime(); 

    // Per 4.2.1.2, use count of uuid's generated during the current clock 
    // cycle to simulate higher resolution clock 
    var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; 

    // Time since last uuid creation (in msecs) 
    var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; 

    // Per 4.2.1.2, Bump clockseq on clock regression 
    if (dt < 0 && options.clockseq == null) { 
     clockseq = clockseq + 1 & 0x3fff; 
    } 

    // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new 
    // time interval 
    if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { 
     nsecs = 0; 
    } 

    // Per 4.2.1.2 Throw error if too many uuids are requested 
    if (nsecs >= 10000) { 
     throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); 
    } 

    _lastMSecs = msecs; 
    _lastNSecs = nsecs; 
    _clockseq = clockseq; 

    // Per 4.1.4 - Convert from unix epoch to Gregorian epoch 
    msecs += 12219292800000; 

    // `time_low` 
    var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; 
    b[i++] = tl >>> 24 & 0xff; 
    b[i++] = tl >>> 16 & 0xff; 
    b[i++] = tl >>> 8 & 0xff; 
    b[i++] = tl & 0xff; 

    // `time_mid` 
    var tmh = (msecs/0x100000000 * 10000) & 0xfffffff; 
    b[i++] = tmh >>> 8 & 0xff; 
    b[i++] = tmh & 0xff; 

    // `time_high_and_version` 
    b[i++] = tmh >>> 24 & 0xf | 0x10; // include version 
    b[i++] = tmh >>> 16 & 0xff; 

    // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) 
    b[i++] = clockseq >>> 8 | 0x80; 

    // `clock_seq_low` 
    b[i++] = clockseq & 0xff; 

    // `node` 
    var node = options.node || _nodeId; 
    for (var n = 0; n < 6; n++) { 
     b[i + n] = node[n]; 
    } 

    return buf ? buf : unparse(b); 
    } 

    // **`v4()` - Generate random UUID** 

    // See https://github.com/broofa/node-uuid for API details 
    function v4(options, buf, offset) { 
    // Deprecated - 'format' argument, as supported in v1.2 
    var i = buf && offset || 0; 

    if (typeof(options) == 'string') { 
     buf = options == 'binary' ? new BufferClass(16) : null; 
     options = null; 
    } 
    options = options || {}; 

    var rnds = options.random || (options.rng || _rng)(); 

    // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` 
    rnds[6] = (rnds[6] & 0x0f) | 0x40; 
    rnds[8] = (rnds[8] & 0x3f) | 0x80; 

    // Copy bytes to buffer, if provided 
    if (buf) { 
     for (var ii = 0; ii < 16; ii++) { 
     buf[i + ii] = rnds[ii]; 
     } 
    } 

    return buf || unparse(rnds); 
    } 

    // Export public API 
    var uuid = v4; 
    uuid.v1 = v1; 
    uuid.v4 = v4; 
    uuid.parse = parse; 
    uuid.unparse = unparse; 
    uuid.BufferClass = BufferClass; 

    if (typeof define === 'function' && define.amd) { 
    // Publish as AMD module 
    define(function() {return uuid;}); 
    } else if (typeof(module) != 'undefined' && module.exports) { 
    // Publish as node.js module 
    module.exports = uuid; 
    } else { 
    // Publish as global (in browsers) 
    var _previousRoot = _global.uuid; 

    // **`noConflict()` - (browser only) to reset global 'uuid' var** 
    uuid.noConflict = function() { 
     _global.uuid = _previousRoot; 
     return uuid; 
    }; 

    _global.uuid = uuid; 
    } 
}).call(this); 

回答

0

這實際上是一個非常有趣的問題,它有很多層次。

首先,值得注意的是uuid.js支持兩種不同形式的id。 uuid.v4()使用隨機數創建ID,而uuid.v1()根據時間戳創建ID。 id的「版本」實際上是在id本身編碼的,這就保證了理論上沒有v4 id會碰到v1 id。這是RFC4122的一部分,即UUID規範。

還值得注意的是,對於v1 ids,每個id源應該有一個唯一的「節點id」,也是在id中編碼的,它保證了由該源創建的id序列的唯一性。對於有權訪問保證唯一值的id源(例如設備的MAC地址),這可以很好地工作。但是,uuid.js無法訪問此類值,因此會爲其節點標識生成一個隨機值。這引入了生成與您的服務器使用的節點ID相匹配的節點ID的風險。節點ID是48位值,這意味着節點ID衝突的可能性是281,474,976,710,656:1。所以,這是一個機會,但它是非常低的。

......但沒有一件事情!

事實證明,即使NewSequentialID()產生的表面上類似於V1的ID標識,微軟for whatever reasons決定將ID內交換各個領域的周圍,打破RFC4122的兼容性。這意味着,根據序列號,這些ID可能看起來像也可能不像有效的v1 id,或有效的v4 id,或者僅僅是無效的UUID。即使用NewSequentialID()如果您想談論uuid碰撞的可能性,請將扳手投入作品中。

我不確定有一個簡單的方法來量化碰撞的風險給這最後一個問題。在一天結束時,UUID是128位值,這意味着有數字空間可用於繪製。除了最苛刻的要求之外,你可能還可以。但是,如果您使用符合RFC的UUID來源,那麼碰撞風險將會增加。

[FWIW,你uuid.js來自the node-uuid project(*咳嗽*撰文稱)。]

+0

感謝您的回答,並可以用來遺忘在那裏我得到了它抱歉。 – sheamus

相關問題