Collision-resistant ids for distributed systems
APACHE-2.0 License
const Bronze = require('bronze')
const idGen = new Bronze({name: 'example'})
const id = idGen.generate()
// 1482810226160-0-14210-example-1a
$ bronze --name example
# 1496196550327-31-7887-example-1a
$ npm install bronze
CLI only:
$ [sudo] npm install bronze -g
UUID1
) or random (UUID4
) collisionstimestamp
or name
const Bronze = require('bronze')
const idGen = new Bronze()
idGen.generate()
// > 1483113483923-0-12179-localhost-1a
idGen.generate()
// > 1483113483923-1-12179-localhost-1a
// continue to create ids throughout your code
A spec determines what goes into an id and how its information is sorted.
Type 1
- contains a timestamp
in milliseconds, a sequence
number, a process id (PID
), and a name
1a
is ordered by timestamp
- sequence
- pid
- name
1482981306438-0-5132-example-1a
1b
is ordered by name
- pid
- timestamp
- sequence
example-5132-1482981317498-0-1b
Bronze
CLASS
static get defaultName
STRING
static get defaultSpec
STRING
static get specs
OBJECT
static parse
(id)
parses an id to JSON-compatible object
id
STRING required
new Bronze (options)
const idGen = new Bronze({name: 'example', sequence: 1})
options
OBJECT
sequence
INTEGER
pid
INTEGER
name
STRING
spec
STRING
instance OBJECT
sequence
INTEGER
pid
INTEGER
name
STRING
nameRaw
STRING
spec
STRING
generate
([options])
const idGen = new Bronze()
const id = idGen.generate()
// > 1482810226160-0-14210-localhost-1a
options
OBJECT optional
json
BOOLEAN
return id STRING | OBJECT
options.json === true
nextSequence
()
const idGen = new Bronze()
idGen.nextSequence()
Using bronze in the browser is pretty straight-forward. As of webpack 3, no special loaders are required to use bronze. Since most browser environments do not support the process
object (with the exception of Electron, NW.js, and the like), you should pass the pid
and name
options to the constructor, like so:
new Bronze({pid: 1, name: 'browser'})
If you are using bronze in a distributed environment you should verify the generated name
via Bronze.parse
in a trusted space, such as the server-side.
The CLI uses the module under the hood.
Usage: bronze [options]
Options:
--sequence INT Set the counter for the number of ids generated
By default will use sequence file (sequence path)
If set sequence file will not be updated
--pid INT Set the process id for generated ids
--name STRING A unique name for the generator
Any slashes will be replaced with underscores
--spec STRING Set the spec
--gen, -g INT The number of ids to create. Must be >= 0.
Default = 1
--list-specs Get the specs available from this version of bronze
--sequence-dir STRING Set the sequence directory
Will attempt to create if not exist
--sequence-dir-reset Sets the sequence back to 0
File isn't created if it doesn't exist
--help, -h
--version, -v
While developing a distributed system using UUID1
and UUID4
we found that we would run into collisions as we scaled.
UUID1
(timeuuids) can have collisions within 100ns, which can happen when migrating/importing data in bulkUUID4
can have collisions at random. While the risk is reasonably small, a chance of data loss does not sit well with us.cluster
module with no additional setupname
may contain any character, including dashes, but slashes (\/) will be replaced with underscores (_).
name
. If every machine has a unique hostname (process.env.HOSTNAME
) you should be fine.name
on a different machine within your distributed system's range of clock skew.name
PID
) to avoid collisions.
cluster
module receives its own PID
so no worries here.Number.MAX_SAFE_INTEGER
(9007199254740991)spec 1a
) is supported up to 2286-11-20T17:46:39.999Z
(9999999999999)text
data types should do the trickCLI
--parse
option
Nested IDs
const id1 = idGen.generate({name: 'example'})
console.log(id1)
// > 1482810226160-0-14210-example-1a
// Nested
idGen.name = id1
const id2 = idGen.generate()
console.log(id2)
// > 1482810226222-1-14210-1482810226160-0-14210-example-1a-1a
Bronze.parse('1482810226222-1-14210-1482810226160-0-14210-example-1a-1a')
// { valid: true,
// timestamp: 1482810226222,
// sequence: 1,
// pid: 14210,
// name: '1482810226160-0-14210-example-1a',
// spec: '1a' }
// can also nest id2, id3, id4, id5, ...idN
See more in FUTURE.md