How to Design Scalable, Unique Order Numbers for High‑Traffic Systems
This article examines common order‑number generation rules and compares four practical solutions—UUID, database auto‑increment, Snowflake algorithm, and Redis INCR—providing code examples and best‑practice recommendations for building globally unique, fast‑producing identifiers in distributed backend systems.
01. Background Introduction
In software development we often need to generate business numbers such as order IDs, inbound‑stock IDs, complaint IDs, etc. This article uses e‑commerce order number rules as a case study, noting that the design principles apply to many other service identifiers.
Order naming rules summary :
Uniqueness : must be globally unique.
Security : should not be easily guessed or reveal business volume.
Avoid random codes : random strings improve security but hurt readability and may still collide.
Concurrency safety : must handle high‑throughput scenarios such as flash sales.
Length control : keep the identifier between 10 and 18 characters for readability.
02. Solution Practice
How can we implement these rules effectively?
2.1 Solution 1: UUID
UUID (Universally Unique Identifier) combines timestamp, MAC address, clock sequence and other data to produce a 128‑bit value. Example format:
00000191-adc6-4314-8799-5c3d737aa7de.
<code>String uuid = UUID.randomUUID().toString();</code>Although easy to generate, UUID strings are long, inefficient for database indexing, and are not suitable for order numbers.
2.2 Solution 2: Database Auto‑Increment
Setting a column as AUTO_INCREMENT lets the database generate sequential IDs without application code. Example MySQL table creation:
<code>CREATE TABLE `tb_user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;</code>This works for monolithic services but suffers from low concurrency and potential duplication when sharding databases in large‑scale distributed environments.
2.3 Solution 3: Snowflake Algorithm
Snowflake (originated by Twitter) generates 64‑bit IDs composed of a sign bit, a 41‑bit timestamp, a data‑center ID, a worker ID, and a 12‑bit sequence number. The structure guarantees time‑ordered, globally unique IDs.
Advantages: monotonic increase, no duplication across nodes. Limitations: generated IDs are 21 characters long, and the 41‑bit timestamp supports up to 69 years of usage, requiring a custom epoch to avoid collisions.
2.4 Solution 4: Distributed Component (Redis INCR)
Using Redis
INCRon a dedicated key provides a fast, globally incremental sequence that works well under high concurrency.
<code>// Based on a key to achieve auto‑increment
String res = jedis.get(key);
if (StringUtils.isBlank(res)) {
// Set initial value
jedisClient.set(key, INIT_ID);
// Set expiration time in seconds
jedisClient.expire(key, seconds);
}
// Increment to obtain order ID
long orderId = jedis.incr(key);
</code>After obtaining a unique sequence, combine it with a time‑based prefix (e.g.,
yyMMdd+ seconds) and a business code to form the final order number.
Example implementation (Java + Redis) that mimics Xiaomi’s 16‑digit rule:
<code>// Get current time
Date currentTime = new Date();
// Format as yyMMdd
String originDateStr = new SimpleDateFormat("yyMMdd").format(currentTime);
// Calculate seconds elapsed since start of the day
Date startTime = new SimpleDateFormat("yyyyMMdd").parse(new SimpleDateFormat("yyyyMMdd").format(currentTime));
long differSecond = (currentTime.getTime() - startTime.getTime()) / 1000;
String yyMMddSecond = originDateStr + StringUtils.leftPad(String.valueOf(differSecond), 5, '0');
// Build Redis key: business code + time part
String prefixOrder = sourceType + "" + yyMMddSecond;
// Increment within the same second (expire after 60 s)
Long incrId = redisUtils.saveINCR(prefixOrder, 60);
// Final order number
String orderNo = prefixOrder + StringUtils.leftPad(String.valueOf(incrId), 4, '0');
</code>This approach guarantees uniqueness, high throughput, and natural time ordering.
03. Summary
For high‑concurrency environments, combining Redis
INCRwith a well‑designed order‑number rule (time prefix, business code, and per‑second sequence) provides fast, globally unique identifiers that also preserve chronological order, making it the preferred solution over UUID, plain auto‑increment, or Snowflake when length and readability are concerns.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.