Skip to content

Commit

Permalink
added short-puid
Browse files Browse the repository at this point in the history
  • Loading branch information
Sascha Droste committed May 16, 2013
1 parent 30cadaa commit 51d8930
Show file tree
Hide file tree
Showing 7 changed files with 554 additions and 69 deletions.
File renamed without changes.
119 changes: 102 additions & 17 deletions README.md
@@ -1,26 +1,50 @@
[![Build Status](https://travis-ci.org/pid/puid.png)](https://travis-ci.org/pid/puid)

# puid - primary unique id
# puid - primary unique id

Generate an unique ID depending on time, machine and process for use in a distributed environment.


## puid - 24 characters uid

Each unique ID has 4 sections and has 24 chars, which are:

i.e. he5fps6l2504cd1w3ag8ut8e // he5fps6l-2504cd-1w3a-g8ut8e

- timestamp: 'he5fps6l' // Timestamp in microseconds - safe until 2059
- machineId: '2504cd' // First 6 chars from md5 of first external network interface or fallback to hostname
- processId: '1w3a' // pid
- counter: 'g8ut8e' // High-resolution real time; nanoseconds
- timestamp: 'he5fps6l' // (8) Timestamp in microseconds - safe until 2059
- machineId: '2504cd' // (6) First 6 chars from md5 of first external network interface or fallback to hostname
- processId: '1w3a' // (4) pid
- counter: 'g8ut8e' // (6) High-resolution real time; nanoseconds

All values (except machineID) are converted to base36.

Why is the counter not really a counter? Because of collision, it's more likely that the same machine and process use (accidently!) two puid-objects (async) and generate an Id at the same microsecond with identical counter. That the same process will execute the counter function within the same nanosecond should be impossible (imo) - feedback is welcome.

## Why it exists?
People are asking why I build this piece of code, there are so many solutions around.
The reason is simple: I wanted an as short as possible primary key for distributed environments. UUIDv4 was not an option for several reasons. One of them is that the id is 36 characters long ;-). Other solutions were not convincing either. Size matters? Yes! :-) 24 is better than 36.

## puid - short puid - 12-14 characters uid

Each unique ID has 2 sections and has 12 chars without nodeId or 14 chars with nodeId, which are:

i.e. aeby6ob5sso4zd // aeby6ob5sso4-zd

- timestamp: 'aeby6ob5sso4' // (12) Timestamp in seconds + hrtime counter
- nodeId: 'zd' // (2) nodeId

After the first puid release, I was testing for some shorter UIDs. In result, the short-puid was born ;-). Works only with node.js (depend on process.hrtime). The process.hrtime[1] gives you an counter (milliseconds+nanoseconds value from 1 to 1_000_000_000) not depending of the current timestamp, in result you can use puid-short (12 chars version) without any conflicts with multi-instances of puid in the same process or in different processes on the same host (tested with 20 parallel instances generating 4 billion puids). With multi nodes/hosts, you have to use the short-version with 14 chars which includes a nodeId.

i.e. aeby6ob5sso4zd // aeby6ob5sso4-zd

- timestamp: 'aeby6ob5sso4' // (12) Timestamp in seconds + hrtime counter
- nodeId: 'zd' // (2) nodeId


### Configurate short-puid

You have options :-) You can pass the epoch to start counting the timestamp, per default we start at "1999-08-02 03:00:00 pm", and you can pass the nodeId. Take a look to the usage section for all possiblities.


## Usecase

Generate unique keys for e.g. Redis.

## Installation
Expand All @@ -40,17 +64,78 @@ $ npm test
## Usage

```js
var Puid = require('puid'),
puid = new Puid();

console.log(puid.generate());
console.log(puid.generate());

// Output:
// he5gawzw2504cd1w6x83z1kr
// he5gawzw2504cd1w6x83ziw1

var Puid = require('puid');
var puid;

// generate puid (long-version 24-chars)

puid = new Puid();
console.log(puid.generate()); // hgqy29gr11cm2504cdf8rg7q


// generate puid (short-version 14-chars) with nodeId string

puid = new Puid('JS');
console.log(puid.generate()); // 3bq1plt0vlycjs


// generate puid (short-version 12-chars) with empty nodeId string

puid = new Puid('');
console.log(puid.generate()); // 3bq1plt1iiw4


// generate puid (short-version 14-chars) with nodeId in config object

puid = new Puid({
nodeId: 'JS'
});
console.log(puid.generate()); // 3bq1plt1ljwgjs


// generate puid (short-version 14-chars) with epoch in config object and random nodeId

puid = new Puid({
epoch: '1980-01-01'
});
console.log(puid.generate()); // 801eeqggvq0w54


// generate puid (short-version 14-chars) with epoch and nodeId in config object

puid = new Puid({
epoch: '1980-01-01',
nodeId: 'JS'
});
console.log(puid.generate()); // 801eeqggyo00js


// generate puid (short-version 12-chars) with epoch and empty nodeId in config object

puid = new Puid({
epoch: '2013-01-01',
nodeId: ''
});
console.log(puid.generate()); // 036pqlnkkjk0


// generate puid (short-version 12-chars) without nodeId / Shortcut new Puid(true)!

puid = new Puid(true);
console.log(puid.generate()); // 3bqk9my968mc


// generate puid (short-version 14-chars) random nodeId / Shortcut new Puid(false)!

puid = new Puid(false);
console.log(puid.generate()); // 3bqk9my9buecut

```

## Changes
- v0.4.0 added short-puid, long-puid behavior is unchanged

## License
[MIT](https://github.com/pid/puid/blob/master/LICENCE.txt)

Expand Down
107 changes: 101 additions & 6 deletions examples/generatePid.js
@@ -1,10 +1,105 @@
var Puid = require('../lib/puid'),
puid = new Puid();
var Puid = require('../lib/puid');

console.dir(puid);
var puid;

for (var i = 0; i < 100; i++) {
console.log(puid.generate());
// ####

console.log("\ngenerate puid (long-version)\n");

puid = new Puid();

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

// ####

console.log("\ngenerate puid (short-version) with nodeId string\n");

puid = new Puid('JS');

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

// ####

console.log("\ngenerate puid (short-version) with empty nodeId string\n");

puid = new Puid('');

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

// ####

console.log("\ngenerate puid (short-version) with nodeId in config object \n");

puid = new Puid({
nodeId: 'JS'
});

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

// ####

console.log("\ngenerate puid (short-version) with epoch in config object and random nodeId\n");

puid = new Puid({
epoch: '1980-01-01'
});

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

// ####

console.log("\ngenerate puid (short-version) with epoch and nodeId in config object\n");

puid = new Puid({
epoch: '1980-01-01',
nodeId: 'JS'
});

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

// ####

console.log("\ngenerate puid (short-version) with epoch and empty nodeId in config object\n");

puid = new Puid({
epoch: '2013-01-01',
nodeId: ''
});

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

// ####

console.log("\ngenerate puid (short-version 12-chars) without nodeId / Shortcut new Puid(true)!\n");

puid = new Puid(true);

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

// ####

console.log("\ngenerate puid (short-version 14-chars) random nodeId / Shortcut new Puid(false)!\n");

puid = new Puid(false);

for (var i = 0; i < 3; i++) {
console.log(puid.generate());
}

console.dir(puid);
//

0 comments on commit 51d8930

Please sign in to comment.