Unique identifiers generation in Node.js


Generating a unique identifier is sometimes a straightforward job. All you need is to get an index of integer type and increment it any time you need an identifier. The things get more complicated if an id needs to be unique in a distributed environment.

In this post, I am sharing a couple of approaches to generated unique identifiers in Node.js. The solutions can be used in a single process as well as the distributed environment.

Using UUID as an identifier

A universal unique identifier (UUID) is a standard of generating ids, standardized by the Open Software Foundation (OSF).

UUIDs intend to be able to generate unique identifiers in a distributed system without central coordination point. The word unique should not be taken to mean guaranteed unique; it is rather practically unique.

UUID canonical form is as follows:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

The N indicates the variant and M indicates the UUID version. You can find all the UUID details in RFC4112

Version 1 UUID is meant for generating time-based UUIDs. They also accept 48 bit long identifier (281,474,976,710,655 available values). In many cases, it makes sense to use a machine MAC Address as an identifier. Sometimes if we use several UUID generators on the same system, we can use configured identifiers. Having a unique identifier in a distributed environment is critical. That will guarantee conflict-free ids.

Version 4 UUID is meant for generating UUIDs from truly-random or pseudo-random numbers. UUID v4 are not giving us guaranteed unique numbers; they are somewhat practically unique.

Probability of UUID v4 duplicates

Only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%.

There are several Node.js modules generating UUID numbers. The one which I use very often is node-uuid. Fast and straightforward implementation of UUID version 1 and 4.

The Node.js uuid module is straightforward to use. You can install it using npm manager:

npm install uuid

And use it in your script e.g.:

const uuidv1 = require('uuid/v1')
const uuidv4 = require('uuid/v4')

var uuid1 = uuidv1()
var uuid2 = uuidv1({ node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab] })
var uuid3 = uuidv1({ node: [0, 0, 0, 0, 0, 0] })
var uuid4 = uuidv4()
var uuid5 = uuidv4()

And that would give something like this. Please note that your results should be completely different than the ones below due to nature of UUID number.

uuid1 v1 => 6af978f0-96ed-11e8-bb38-37f5ae311cf6
uuid2 v1 => 6af978f1-96ed-11e8-bb38-0123456789ab
uuid3 v1 => 6af978f2-96ed-11e8-bb38-000000000000
uuid4 v4 => 229f6276-5ea0-4c93-a022-d63f856cdf93
uuid5 v4 => 318edf5f-a99d-42a5-98a4-a07ab58a645e

Generate identifiers using Snowflake approach

An alternative to UUID identifiers might be 64 bit long identifiers generated using Twitter Snowflake approach. A couple of years ago I created Node.js flake-idgen module which generates ids meeting following requirements:

  • Uncoordinated - services generating ids should not have any central coordination point. That is very important for high availability services.
  • Compact - generated ids are 64-bit long. Other good solutions are generating bigger ids, e.g., 128-bit long UUIDs.
  • (Roughly) Time ordered - the ids will be k-ordered (roughly ordered), i.e., ids are no more than k positions from its totally ordered position.
  • Good performance - a service generating ids can produce up to 4096 ids per millisecond.

The Node.js flake-idgen module is straightforward to use. You can install it using npm manager:

npm install flake-idgen

And use it in your script e.g.:

var FlakeIdGen = require('flake-idgen'),
    intformat = require('biguint-format'),
    generator = new FlakeIdGen()

var id1 = generator.next()
var id2 = generator.next()

var id3 = intformat(id1, 'dec')
var id4 = intformat(id2, 'dec')

var id5 = intformat(id1, 'hex', { prefix: '0x' })
var id6 = intformat(id2, 'hex', { prefix: '0x' })

And that would give you following results:

id1 => <Buffer 59 3f aa b9 a4 80 00 00>
id2 => <Buffer 59 3f aa b9 a5 00 00 00>
id3 => '6431046507213881344'
id4 => '6431046507222269952'
id5 => 0x593faab9a4800000
id6 => 0x593faab9a5000000

Conclusion

There are several other solutions to generate unique identifiers. Some of them may be good for distributed environments; some others may work only on a single node.

In this post, I wanted to share with you some simple solutions producing unique identifiers in distributed environments which could be implemented in Node.js in production systems.


Tags:

#identifier #javascript #node.js #random #uuid


You may also be interested in:



comments powered by Disqus