Rethinking 12306 Ticketing: A Domain‑Driven Design Model for High‑Concurrency Reservations

This article analyzes the unique complexities of China's 12306 train ticketing system, proposes a domain‑driven aggregate model centered on train trips, explains seat‑allocation rules and overlapping interval handling, and outlines a CQRS and event‑sourcing architecture to achieve strong consistency and high concurrency.

ITPUB
ITPUB
ITPUB
Rethinking 12306 Ticketing: A Domain‑Driven Design Model for High‑Concurrency Reservations

Demand Overview

The 12306 system must support three core scenarios: users querying seat availability, users purchasing tickets, and the railway authority issuing tickets. Unlike typical e‑commerce where a product has a fixed inventory, train tickets are sold for variable station‑to‑station segments, making the business logic far more intricate.

Demand Analysis

Each ticket can be seen as a product, but the number of possible tickets (SKUs) explodes because a train with n stations yields n·(n‑1)/2 possible station‑pair intervals. For example, the G71 train with 17 stations can theoretically sell thousands of tickets, far exceeding the physical seat count.

A ticket’s core data includes departure time, origin, destination, train number, and seat number. The ticket is a credential for the passenger and a commitment for the railway authority.

Because seats can be reused on non‑overlapping intervals, the same physical seat may be sold multiple times for different segments, effectively increasing the total sellable tickets.

Four interval relationships are identified: non‑overlapping, partially overlapping, fully overlapping, and covering. The key business rule is that for any atomic segment (adjacent stations), the number of overlapping tickets plus one must not exceed the train’s total seat count.

Model Design

Traditional E‑commerce Approach

Treating each station‑pair ticket as an independent product leads to thousands of aggregates, massive transactional updates, and severe concurrency conflicts.

Proposed Approach

Make the train trip the aggregate root. The trip aggregate stores:

Train identifier (e.g., G71)

Seat capacity (by class)

Ordered list of stations

Departure time

The aggregate owns the responsibility of ticket issuance, maintaining the available count for each atomic segment.

Ticket Issuance Logic

When a purchase request arrives, the system:

Derives all atomic segments covered by the requested origin‑destination interval.

Attempts to decrement the available count of each segment by one.

If all decrements succeed, the purchase succeeds; otherwise it fails and the user is notified of sold‑out status.

Refund simply increments the same atomic segment counts.

Seat Allocation Strategy

The aggregate also tracks which seats have been assigned to which sold tickets. Two allocation strategies are discussed:

Prefer fresh seat pool : Assign the first free seat, then reuse seats only when necessary. This yields higher throughput but may cause a passenger to change seats mid‑journey.

Prefer seat reuse : Scan for seats that can be reused across the requested interval, ensuring the passenger stays in the same seat for the whole trip. This avoids seat changes at the cost of extra scanning.

The article recommends the reuse‑first strategy to prevent mid‑journey seat swaps.

Model Analysis Summary

Tickets are not core aggregates; they are the result of a ticket‑issuance operation.

The train trip aggregate encapsulates issuance, seat selection, atomic‑segment inventory updates, and sold‑ticket records.

This design confines all state changes to a single aggregate, guaranteeing strong consistency without database‑level transactions and enabling high‑concurrency processing.

Architecture Design (Optional)

A CQRS architecture fits the scenario: write side handles complex ticket issuance using the trip aggregate, while the read side serves high‑volume queries via distributed caches.

Write‑Side Implementation

Using a framework like ENode, the system can employ in‑memory aggregates with Event Sourcing. Each ticket‑issuance command generates a single domain event (JSON), persisting only the event and avoiding heavyweight ORM transactions.

Read‑Side Implementation

Querying seat availability (≈80% of traffic) can be served from caches. Cache keys can be designed either per full origin‑destination‑date combination (high key count, O(1) lookup) or per atomic segment (lower key count, slight extra computation). Event‑driven updates keep the cache near real‑time.

Conclusion

The proposed domain model and CQRS‑Event‑Sourcing architecture demonstrate how to handle the 12306 system’s combinatorial ticket space, ensure strong consistency, and achieve high throughput. Real‑world implementation would require close collaboration with domain experts to refine rules and constraints.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Software ArchitectureconcurrencyDomain-Driven DesignticketingCQRSEvent Sourcing
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

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.