Redis Distributed ID Generator with SpringBoot 3.0
The article presents a Redis‑based distributed ID generator for Spring Boot 3.0 that uses an atomic INCR on a Redis string to produce compact, monotonic, globally unique numeric identifiers, synchronizes the maximum value with MySQL on startup, and offers high performance, availability, and low storage overhead.
Generating globally unique identifiers is a common requirement for request tracing, order numbers, or user IDs. While UUIDs provide uniqueness, they suffer from two major drawbacks for database primary keys: they are not monotonic, causing frequent B+Tree page splits in MySQL, and they consume excessive memory because each UUID is a 36‑character string.
To overcome these issues, a Redis‑based distributed ID generator is presented. The solution leverages Redis strings and the atomic INCR command to produce sequential numeric IDs that are both globally unique and ordered.
Requirements for a Distributed ID
Monotonic increase – ensures B+Tree indexes remain ordered and avoids page splits.
Global uniqueness – prevents primary‑key conflicts.
High performance – ID generation is a high‑frequency operation.
High availability – the service must be reliable.
Compact storage – small numeric IDs reduce index size and I/O.
Redis String Implementation
Redis clusters provide high availability and performance. By storing the ID as a numeric value in a Redis string, the INCR command atomically increments the value, guaranteeing uniqueness without additional locking.
To avoid data loss on restart, enable Redis AOF persistence (e.g., everysec ) and optionally persist the maximum ID to MySQL via an asynchronous mechanism.
Design Flow
On application startup, read the maximum ID M from MySQL. Check if the Redis key counter:order exists with EXISTS counter:order . If not, set the key to SET counter:order M . If it exists, compare the Redis value K with M and store the larger one with SET counter:order max(M, K) .
When an ID is needed, issue INCR counter:order to obtain the next value.
Publish the generated ID to a message queue; a consumer writes the value back to MySQL.
SpringBoot 3.0 Implementation
Add the Redis starter dependency to pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>Configure the Redis connection in application.yml :
spring:
application:
name: redis
redis:
host: 127.0.0.1
port: 6379
password: magebyte
timeout: 6000Create a generator component that interacts with Redis:
@Component
public class OrderIdGenerator implements InitializingBean {
private final StringRedisTemplate redisTemplate;
private final IdGeneratorMapper idGeneratorMapper;
private static final String KEY = "counter:order";
private String dbId;
@Autowired
public OrderIdGenerator(StringRedisTemplate redisTemplate, IdGeneratorMapper idGeneratorMapper) {
this.redisTemplate = redisTemplate;
this.idGeneratorMapper = idGeneratorMapper;
}
public Long generateId(String key) {
return redisTemplate.opsForValue().increment(key, 1);
}
@Override
public void afterPropertiesSet() throws Exception {
// Retrieve max ID from DB
this.dbId = idGeneratorMapper.getMaxID(KEY);
Boolean hasKey = redisTemplate.hasKey(KEY);
if (Boolean.TRUE.equals(hasKey)) {
// Compare DB and Redis values, keep the larger one
String redisValue = redisTemplate.opsForValue().get(KEY);
String targetValue = max(this.dbId, redisValue);
} else {
// Initialize Redis with DB max value
redisTemplate.opsForValue().set(KEY, dbId);
}
}
}For custom business‑specific IDs (e.g., ORD-20240528-0001 ), add a method that formats the numeric sequence with a prefix and date pattern:
public String generateCustomId(String key, String prefix, String datePattern) {
long sequence = redisTemplate.opsForValue().increment(key, 1);
return String.format("%s-%s-%04d", prefix, new SimpleDateFormat(datePattern).format(new Date()), sequence);
}Use the generator in a service layer:
@Service
public class OrderService {
private final RedisIdGenerator idGenerator;
@Autowired
public OrderService(RedisIdGenerator idGenerator) {
this.idGenerator = idGenerator;
}
public Order createOrder(OrderRequest request) {
String orderId = idGenerator.generateCustomId("order:id", "ORD", "yyyyMMdd");
Order order = new Order();
order.setId(orderId);
// other business logic ...
return order;
}
}This approach delivers a high‑performance, highly available, and memory‑efficient ID generation mechanism suitable for backend systems that require ordered, globally unique identifiers.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
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.