A customizable distributed unique ID generator inspired by Twitter's Snowflake.
More functions are as follows.
- Bit field length and layout can be customized.
- Field values (timestamp, machine id, etc) can be easily parsed from ID.
- ID generation with the specified value (snapshot function). This is useful for creating SQL queries that you want to filter with a range of the timestamp field of ID.
- Transparently handle inverted bits.
- Both binary (byte []) and long id can be generated.
// Get Long(64bit) ID generator. That is thread-safe.
Id64Gen snowflake = Id64Gen.builder()
.nextBit(1).unusedField() // Sign Bit
.nextBit(41).timestampField()
.tickPerMillisec()
.startAt(Instant.parse("2017-01-01T00:00:00.00Z"))
.nextBit(5).constantField()
.name("data-center-id").value(1)
.nextBit(5).constantField()
.name("worker-id").value(2)
.nextBit(12).sequenceField()
.build();
// Generate unique ID.
Long id = snowflake.next().id();
// Parse timestamp.
Instant parsedTime = snowflake.parseTimestamp(id);
// Get ID with specified values.
Long id2 = snowflake.snapshot()
.putTimestamp(Instant.parse("2017-01-01T00:00:00.00Z"))
.putSequence(Long.valueOf(100))
.id();
This library is release in JitPack. Latest version is
You can see how to add this library to your project on the JitPack page.
You can combine the following field types. Following a specifiying the bit length with nextBit()
, call the function that generates the field builder to select the field type.
All field builders transparently support bit flipping by the flip()
function.
timestampField()
creates a timestamp field builder.- ID can contain at most one of this field.
startAt()
tells epoch to the generator. Required.tickPerMilliSec()
ortickPerSecond()
defines the tick. Also, if you want to customize the tick, usewithTimestampGenerator()
sequenceField()
creates a sequence field builder.- ID can contain at most one of this field.
startAt()
defines the origin of sequence. Default is 0.- You can customize sequencer with
sequencer()
.
constantField()
creates a constant value field builder.- ID can contain any number of this field.
- This field has
name()
andvalue()
. ID Generator always sets a fixedvalue()
in the bit field. - Name is used for parsing.
bindableField()
creates a bindable value field builder.- ID can contain any number of this field.
- You need to specify the 'bindable' value each time an ID is generated for the ID containing bindable field.
name()
defines the field name.
Id64Gen gen = Id64Gen.builder()
.nextBit(1).unusedField()
.nextBit(31).bindableField().name("worker")
.nextBit(32).sequenceField()
.build();
// Generates id with specified worker.
Long id = gen.next().bind("worker", 1).id();
If you want to generate a binary ID, use IdBytesGen
.
// IdBytesGen.builder() takes the length of bytes
IdBytesGen gen = IdBytesGen.builder(13)
.nextBit(10).bindableLongField().name("cluster")
.nextBit(32).bindableField().name("group-hash")
.nextBit(42).timestampField().tickPerMillisec().startAt(Instant.parse("2017-01-01T00:00:00.00Z"))
.nextBit(20).sequenceField()
.build();
byte[] id = gen.next().id();