Photo by Aaron Burden on Unsplash
Using Snowflake ID Generator for Unique IDs in Spring Boot
Using a Snowflake ID server to produce one-of-a-kind IDs in Spring Boot
Introduction
The Snowflake ID Server is a Spring Boot-based microservice designed to generate distributed, unique, and time-ordered identifiers using Twitter's Snowflake algorithm. The project supports two implementations of Snowflake ID generation:
Hutool-based Implementation (Using Hutool's built-in Snowflake generator).
Custom Implementation (A fully customized version of the Snowflake algorithm).
What is a Snowflake ID?
A Snowflake ID is a unique, time-ordered, and distributed 64-bit identifier used in large-scale systems. It was originally developed by Twitter to address the scalability issues of traditional incremental ID systems.
Each Snowflake ID consists of multiple segments that encode the timestamp, machine ID, datacenter ID, and a sequence number. This structure ensures that IDs are globally unique and sortable by time.
How Does Snowflake ID Work?
A Snowflake ID is composed of the following:
Bits | Field | Description |
1 | Sign Bit | Always 0 (ensuring positive values). |
41 | Timestamp | The current time in microseconds since a fixed epoch. |
5 | Datacenter ID | Identifies the datacenter running the service. |
5 | Machine ID | Identifies the machine generating the ID. |
12 | Sequence | A counter that increments if multiple IDs are generated within the same timestamp. |
Example Snowflake ID Generation
Imagine a factory where each product is given a unique label before it is shipped. The label contains:
Date of manufacturing (Timestamp)
Factory ID (Datacenter ID)
Production Line ID (Machine ID)
Item Number of the day (Sequence Number)
For example, on February 15, 2024, at exactly 12:00 PM, in Factory 1, on Machine 3, the 56th item of the day is produced.
The Snowflake ID generated for this item will contain:
Timestamp representing February 15, 2024, 12:00 PM.
Datacenter ID = 1 (Factory 1)
Machine ID = 3 (Production Line 3)
Sequence Number = 56 (56th item produced at that time)
The generated ID is unique and ensures that no two items receive the same label, while also allowing easy chronological sorting.
This guide will walk you through the architecture, implementation details, and usage of the Snowflake ID Server.
Project Structure
📦 snowflake-id-server
├── 📂 src/main/java/com/naman/jain/snowflake/id/server
│ ├── 📂 controller # API Controllers
│ │ ├── SnowflakeIdController.java
│ ├── 📂 service # Services for ID generation
│ │ ├── IdGeneratorService.java
│ │ ├── SnowflakeIdGenerator.java
│ ├── 📂 constants # Constant definitions
│ │ ├── SnowflakeConstants.java
├── 📄 application.properties # Configuration properties
├── 📄 pom.xml # Maven dependencies and build config
Key Features
✅ Generates 64-bit unique IDs with time-ordering.
✅ Supports both Hutool and Custom Snowflake implementations.
✅ Allows dynamic machine ID and datacenter ID configuration.
✅ Exposes a REST API to fetch Snowflake IDs.
1️⃣ API Endpoints
Generate a Snowflake ID
GET /v1/api/id/generate?machineId=1&datacenterId=1&type=custom
Query Parameters:
Parameter | Type | Required | Description |
machineId | long | Yes | The machine ID (0-31) |
datacenterId | long | Yes | The datacenter ID (0-31) |
type | String | No | custom (default) or hutool |
Example Response:
1234567890123456789
2️⃣ Custom Snowflake Implementation
The custom Snowflake algorithm is implemented in SnowflakeIdGenerator.java
. The generated 64-bit ID consists of:
Bits | Field | Description |
1 | Sign Bit | Always 0 (positive number). |
41 | Timestamp | Microseconds since a custom epoch. |
5 | Datacenter ID | Identifies the datacenter. |
5 | Machine ID | Identifies the machine. |
12 | Sequence | Auto-incrementing counter per microsecond. |
ID Generation Logic
The nextId
method is responsible for generating a unique Snowflake ID using the current timestamp, machine ID, datacenter ID, and sequence number.
Get the current timestamp (
System.currentTimeMillis()
).Check if the timestamp is the same as the previous request:
If yes, increment the sequence number to differentiate IDs generated in the same millisecond.
If the sequence number exceeds the limit (
MAX_SEQUENCE
), wait until the next microsecond (waitNextMicros()
).If no, reset the sequence to 0.
Update the last recorded timestamp to track the most recent ID generation time.
Construct the final 64-bit ID using bitwise shifts and logical OR operations to combine all components.
public synchronized long nextId(long machineId, long datacenterId) {
long timestamp = System.currentTimeMillis();
if (timestamp == lastTimestamp.get()) {
long seq = (sequence.incrementAndGet()) & MAX_SEQUENCE;
if (seq == 0) {
timestamp = waitNextMicros(timestamp);
}
} else {
sequence.set(0L);
}
lastTimestamp.set(timestamp);
return ((timestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT)
| (datacenterId << DATACENTER_ID_SHIFT)
| (machineId << MACHINE_ID_SHIFT)
| sequence.get();
}
Handling Clock Drift
The waitNextMicros
method ensures that the system waits until the next microsecond if the sequence number reaches its maximum limit within the same millisecond. This prevents duplicate IDs from being generated in high-throughput environments.
Continuously check if the current timestamp is still equal to the last recorded timestamp.
If true, fetch the system's nanosecond timestamp and convert it to microseconds (
System.nanoTime() / 1000
).Return the updated timestamp once it advances past the last recorded timestamp.
This ensures that the Snowflake ID generation process remains sequential, unique, and time-ordered without conflicts.
private long waitNextMicros(long timestamp) {
while (timestamp <= lastTimestamp.get()) {
timestamp = System.nanoTime() / 1000;
}
return timestamp;
}
3️⃣ Hutool-Based Snowflake ID Generation
Hutool is a lightweight Java library that includes a Snowflake ID generator. The implementation is defined in IdGeneratorService.java
:
private Snowflake getSpecificSnowflake(long machineId, long datacenterId) {
return IdUtil.getSnowflake(machineId, datacenterId);
}
4️⃣ Dependencies (pom.xml)
The project uses the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.35</version>
</dependency>
6️⃣ Running the Application
1. Clone the Repository
git clone https://gitlab.com/spring-boots/snowflake-id-server.git
cd snowflake-id-server
2. Build and Run
mvn clean install
mvn spring-boot:run
3. Test the API
curl "http://localhost:8080/v1/api/id/generate?machineId=1&datacenterId=1&type=custom"
# 1955036837781311488
7️⃣ Conclusion
The Snowflake ID Server provides a scalable and efficient way to generate distributed unique identifiers. With support for Hutool and custom implementations, this service can be easily integrated into distributed applications that require high-throughput and time-ordered IDs.