Backend Development 12 min read

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.

macrozheng
macrozheng
macrozheng
How to Design Scalable, Unique Order Numbers for High‑Traffic 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

INCR

on 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

INCR

with 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.

distributed systemsBackend DevelopmentRedissnowflakeunique identifierorder ID
macrozheng
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.