How to Build a Million‑User Ticket Spike System with Nginx Load Balancing and Redis

This article explores the design of a high‑concurrency ticket‑spike system, covering multi‑layer load balancing, weighted Nginx routing, pre‑deduction inventory strategies using Redis, Go implementation details, and performance testing that demonstrates handling millions of requests while preventing oversell and ensuring high availability.

21CTO
21CTO
21CTO
How to Build a Million‑User Ticket Spike System with Nginx Load Balancing and Redis

Introduction

During holidays, people rush to buy train tickets, creating extreme concurrency that can cause the ticket‑selling service to become unavailable within seconds.

High‑Concurrency Architecture

The 12306 service endures the highest QPS of any flash‑sale system, handling millions of simultaneous requests. A typical solution distributes traffic across a distributed cluster, adds multiple layers of load balancing, and provides various disaster‑recovery mechanisms such as dual data centers and node failover.

Load‑Balancing Methods

Three common Nginx load‑balancing strategies are used:

Round‑Robin

Weighted Round‑Robin

IP‑Hash Round‑Robin

Weighted round‑robin is demonstrated with a concrete Nginx configuration that assigns different weights to four backend ports (1, 2, 3, 4).

Ticket‑Spike System Design

Three basic stages are required for a ticket‑spike system: order creation, inventory deduction, and user payment. Directly performing these steps in a single transaction leads to heavy database I/O and risks over‑selling or under‑selling tickets, especially under extreme concurrency.

Pre‑Deduction (Buffer) Strategy

To avoid database bottlenecks, the system first reserves inventory locally in memory (pre‑deduction). If the local stock is sufficient, the request proceeds; otherwise it fails immediately. After a successful local deduction, a remote Redis hash is updated atomically using a Lua script to guarantee that total sales never exceed total inventory.

Implementation in Go

package main

import (
    "net/http"
    "os"
    "strings"
)

func main() {
    http.HandleFunc("/buy/ticket", handleReq)
    http.ListenAndServe(":3001", nil)
}

func handleReq(w http.ResponseWriter, r *http.Request) {
    // request handling logic
}

func writeLog(msg string, logPath string) {
    fd, _ := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
    defer fd.Close()
    content := strings.Join([]string{msg, "
"}, "")
    fd.Write([]byte(content))
}

The Go program initializes local stock, connects to a Redis pool (using Redigo), defines a Lua script for atomic remote deduction, and runs an HTTP server that processes ticket‑buy requests. A channel of size 1 acts as a lightweight distributed lock to serialize access to shared counters.

Performance Test

Using ApacheBench (ab) with 10 000 total requests and 100 concurrent connections, the service achieved approximately 4 300 requests per second, an average latency of 23 ms, and a uniform distribution of traffic across the weighted backends (weights 1‑4). The log file confirmed correct stock accounting.

ab -n 10000 -c 100 http://127.0.0.1:3005/buy/ticket

Takeaways

Distribute traffic with multi‑layer load balancing to reduce per‑node load.

Use in‑memory pre‑deduction and Redis atomic operations to avoid costly database I/O.

Leverage Go’s native concurrency (goroutines, channels) for high‑throughput request handling.

Design buffer stock in Redis to tolerate node failures without causing under‑selling.

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.

load balancingredisGoNGINXticket spike
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

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.