How to Integrate a High‑Performance Snowflake UID Generator into Spring Boot
This guide explains how to integrate the Java‑based Snowflake UIDGenerator into a Spring Boot 2.3 application, covering algorithm fundamentals, RingBuffer optimization, database setup, Maven dependencies, configuration beans, and a test case to generate high‑throughput unique IDs.
Introduction
UidGenerator is a Java implementation of the Snowflake algorithm for generating unique IDs. It works as a component in applications, supports custom workerId bits and initialization strategies, making it suitable for Docker and other virtualized environments where instances may restart or drift.
It solves the natural concurrency limit of the sequence by borrowing future time, uses a RingBuffer to cache generated UIDs, parallelizes production and consumption, and pads CacheLine to avoid hardware‑level false sharing. Single‑machine QPS can reach 6 million.
Dependencies: Java 8+, MySQL (required only for the built‑in WorkerID allocator; optional if you provide your own implementation).
Snowflake Algorithm
The algorithm generates a 64‑bit (long) unique ID composed of:
sign (1 bit) – fixed to 1, ensuring a positive UID.
delta seconds (28 bits) – seconds elapsed since the epoch 2016‑05‑20, supporting about 8.7 years.
worker id (22 bits) – machine identifier, supporting roughly 4.2 million restarts; default allocation is via database.
sequence (13 bits) – per‑second counter, allowing up to 8192 IDs per second.
All parameters can be customized through Spring.
CachedUidGenerator
Uses a RingBuffer where each slot stores a UID. The buffer size defaults to 2^N (the maximum sequence value) and can be expanded via
boostPowerto increase read/write throughput.
Two pointers manage the buffer:
Tail – the highest index produced by the producer; cannot overtake the consumer cursor. When Tail catches up, a rejectedPutBufferHandler can define a PutRejectPolicy.
Cursor – the lowest index consumed; cannot exceed Tail. When Cursor catches up, a rejectedTakeBufferHandler can define a TakeRejectPolicy.
CachedUidGenerator employs two RingBuffers: one for UIDs and another for UID state flags (fillable or consumable). Continuous memory allocation maximizes CPU cache usage, while CacheLine padding mitigates false sharing.
RingBuffer Fill Timing
Initialization pre‑fill – fill the entire buffer at startup.
Immediate fill – during consumption, if the remaining slots (tail‑cursor) fall below a threshold, they are replenished; the threshold is configurable via paddingFactor .
Periodic fill – a scheduled thread refills empty slots at intervals set by scheduleInterval .
UIDGenerator Download
Download the uid‑generator from the provided link.
UIDGenerator Environment Setup
Create the worker node table:
<code>DROP TABLE IF EXISTS WORKER_NODE;
CREATE TABLE WORKER_NODE (
ID BIGINT NOT NULL AUTO_INCREMENT COMMENT 'auto increment id',
HOST_NAME VARCHAR(64) NOT NULL COMMENT 'host name',
PORT VARCHAR(64) NOT NULL COMMENT 'port',
TYPE INT NOT NULL COMMENT 'node type: ACTUAL or CONTAINER',
LAUNCH_DATE DATE NOT NULL COMMENT 'launch date',
MODIFIED TIMESTAMP NOT NULL COMMENT 'modified time',
CREATED TIMESTAMP NOT NULL COMMENT 'created time',
PRIMARY KEY(ID)
) COMMENT='DB WorkerID Assigner for UID Generator' ENGINE=INNODB;</code>Copy the mapper XML,
WorkerNodeEntity,
WorkerNodeDAO, and
DisposableWorkerIdAssignerinto your project. Adjust the DAO injection in
DisposableWorkerIdAssigneras needed.
Project Configuration
Dependencies:
<code><dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency></code>MyBatis configuration:
<code>pagehelper:
helperDialect: mysql
reasonable: true
pageSizeZero: true
offsetAsPageNum: true
rowBoundsWithCount: true
---
mybatis:
type-aliases-package: com.pack.domain
mapper-locations:
- classpath:/mappers/*.xml
configuration:
lazy-loading-enabled: false
aggressive-lazy-loading: false</code>Update the mapper namespace and domain classes to match your package.
Configure UIDGenerator
<code>@Configuration
public class UIDConfig {
@Bean
public DefaultUidGenerator defaultUidGenerator(DisposableWorkerIdAssigner disposableWorkerIdAssigner) {
DefaultUidGenerator defaultUidGenerator = new DefaultUidGenerator();
defaultUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner);
defaultUidGenerator.setTimeBits(29);
defaultUidGenerator.setWorkerBits(21);
defaultUidGenerator.setSeqBits(13);
defaultUidGenerator.setEpochStr("2021-01-01");
return defaultUidGenerator;
}
}</code>Note:
DisposableWorkerIdAssignermust be copied into your project; it is not provided by the library.
<code>@Component
public class DisposableWorkerIdAssigner implements WorkerIdAssigner {
@Resource
private WorkerNodeMapper workerNodeDAO;
// other code
}</code>All configurations are now complete.
Testing
<code>@Resource
private DefaultUidGenerator uidGenerator;
@Test
public void testGeneratorId() {
for (int i = 0; i < 10; i++) {
System.out.println(uidGenerator.getUID());
}
}</code>Run the test to see generated IDs.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.