Hypersistence TSID

repository·master·Indexed 43 days ago

https://github.com/vladmihalcea/hypersistence-tsid

A Java library for generating 64-bit, time-sorted, URL-safe unique identifiers (TSID) that combine features from Twitter's Snowflake and the ULID specification. Version 2.1.4 provides a thread-safe TSID.Factory to generate identifiers as TSID objects, longs, or Crockford's base32 encoded strings, with support for custom epochs, node identifiers, and node bit configurations.

Tokens
1.3K
Snippets
5
Records
8
Agent score
6%

What's inside Hypersistence TSID

  1. Understand the TSID structure

    master

    A TSID (Time-Sorted ID) is a 64-bit integer composed of two main parts:

    1. Time component (42 bits): Milliseconds since 2020-01-01 00:00:00 UTC. This allows for ~69 years of usage in a signed 64-bit integer, or ~139 years in an unsigned field.
    2. Random component (22 bits): Split into:
      • Node ID: Defaults to 10 bits (1,024 nodes), but is adjustable from 0 to 20 bits.
      • Counter: The remaining bits (e.g., 12 bits if node is 10 bits), allowing for a specific number of TSIDs per millisecond (e.g., 4,096).

    The time component can be slightly ahead of system time to maintain monotonicity and generation speed.

  2. Install hypersistence-tsid via Maven

    master

    Add the following dependency to your pom.xml to use the TSID generator in your Java project.

    <!-- https://central.sonatype.com/artifact/io.hypersistence/hypersistence-tsid -->
    <dependency>
        <groupId>io.hypersistence</groupId>
        <artifactId>hypersistence-tsid</artifactId>
        <version>2.1.4</version>
    </dependency>
  3. Generate and use TSIDs

    master

    You can generate TSIDs using the default TSID.Factory. The generator is thread-safe. You can retrieve the TSID as a TSID object, a long, or a String (Crockford's base32 encoded).

    // Create a TSID object
    TSID tsid = TSID.Factory.getTsid();
    
    // Create a TSID as long
    long number = TSID.Factory.getTsid().toLong();
    
    // Create a TSID as String (13 chars, Crockford's base32)
    String string = TSID.Factory.getTsid().toString();
  4. Configure the Node Identifier

    master

    To avoid collisions in distributed systems, each generator should have a unique Node ID. You can configure this via System Properties or Environment Variables.

    System Properties:

    • tsid.node: The specific node identifier.
    • tsid.node.count: The total number of nodes (this automatically adjusts the number of bits reserved for the node ID).

    Environment Variables:

    • TSID_NODE: The specific node identifier.
    • TSID_NODE_COUNT: The total number of nodes.

    Examples:

    # Using System Properties in VM arguments
    -Dtsid.node="755"
    -Dtsid.node="42" -Dtsid.node.count="100"
    
    # Using Environment Variables
    export TSID_NODE="492"
    export TSID_NODE="123"
    export TSID_NODE_COUNT="200"
  5. Configure a custom TSID.Factory

    master

    Use the TSID.Factory.builder() to create specialized generators. You can customize the node bits, the node ID, the epoch, and the random number generation function.

    Common configurations:

    // Factory with fixed node and custom node bits
    TSID.Factory factory = TSID.Factory.builder()
        .withNodeBits(6)      // max: 2^6 = 64 nodes
        .withNode(63)         // max node ID
        .build();
    
    // Factory with a custom epoch
    Instant customEpoch = Instant.parse("1989-11-09T00:00:00Z");
    TSID.Factory factory = TSID.Factory.builder().withCustomEpoch(customEpoch).build();
    
    // Factory using ThreadLocalRandom for performance
    TSID.Factory factory = TSID.Factory.builder()
        .withRandomFunction(() -> ThreadLocalRandom.current().nextInt())
        .build();
    
    // Factory mimicking Twitter Snowflake structure
    int node = (datacenter << 5 | worker);
    Instant twitterEpoch = Instant.ofEpochMilli(1288834974657L);
    TSID.Factory factory = TSID.Factory.builder()
        .withRandomFunction(x -> new byte[x]) // Resets counter on ms change
        .withCustomEpoch(twitterEpoch)
        .withNode(node)
        .build();
  6. TSID Transformation and Utility Methods

    master

    The TSID object provides several methods for manipulation and conversion:

    • TSID.fast(): Creates a quick TSID.
    • TSID.from(String): Creates a TSID from a 13-character canonical string.
    • tsid.toLong(): Returns the internal 64-bit long value.
    • tsid.toString(): Returns the 13-character Crockford's base32 string.
    • tsid.toLowerCase(): Returns the base32 string in lower case.
    • tsid.getInstant(): Returns the Instant representing the creation time.
    • tsid.encode(int radix): Encodes the TSID to a different base (e.g., 62).
    • tsid.format(String pattern): Formats the TSID using a placeholder (e.g., tsid.format("K%S")).
    TSID tsid = TSID.fast();
    String lower = tsid.toLowerCase();
    Instant time = tsid.getInstant();
    String base62 = tsid.encode(62);
    String formatted = tsid.format("K%S");