Designing a Robust High‑Concurrency Flash‑Sale System: Architecture & Rate‑Limiting
This article examines the challenges of flash‑sale (秒杀) systems—such as overselling, massive concurrency, URL exposure, and database strain—and presents a comprehensive backend design that includes dedicated databases, dynamic URLs, static page generation, Redis clustering, Nginx load balancing, SQL optimization, rate‑limiting, asynchronous order processing, and service degradation strategies.
1. Key Issues in Flash‑Sale Systems
Overselling – inventory may be limited but requests exceed stock, causing financial loss.
High concurrency – thousands of users request within minutes, stressing cache and database.
Interface abuse – bots generate hundreds of requests per second, requiring anti‑scraping measures.
Predictable URL – static URLs can be discovered and exploited.
Database coupling – sharing the same DB with other services risks cascade failures.
Massive request volume – single‑node Redis cannot handle hundreds of thousands of QPS.
2. Architectural Design and Technical Solutions
2.1 Dedicated Flash‑Sale Database
Separate tables for flash‑sale orders and goods, optionally additional tables for product details and user information, to isolate high‑traffic operations from the main database.
2.2 Dynamic Flash‑Sale URL
Generate the sale URL by MD5‑hashing a random string; the front‑end requests the URL from the back‑end, which validates it before allowing the purchase.
2.3 Page Staticization
Render product description, parameters, and reviews into a static HTML page using a template engine (e.g., FreeMarker) so the front‑end can serve content without hitting the back‑end or database.
2.4 Redis Cluster & Sentinel
Use Redis for read‑heavy, write‑light workload; deploy a Redis cluster with Sentinel for high availability and to avoid cache‑penetration.
2.5 Nginx Front‑End Proxy
Place Nginx before Tomcat to handle tens of thousands of concurrent connections, distributing traffic to a Tomcat cluster.
2.6 SQL Optimization & Optimistic Lock
Combine stock check and decrement into a single UPDATE statement with a version field for optimistic locking, reducing round‑trips and preventing oversell.
update miaosha_goods set stock = stock-1 where goods_id = #{goods_id} and version = #{version} and stock > 0;2.7 Redis Pre‑Decrement
Initialize stock in Redis (e.g., Redis.set(goodsId, 100)). Each order decrements the Redis value atomically (via Lua script) and falls back to the database only when necessary; cancelled orders increment the Redis count.
2.8 Rate Limiting
Three layers of protection:
Front‑end button disabling for a few seconds after click.
Reject repeated requests from the same user within a configurable interval (e.g., 10 seconds) using Redis key expiration.
Token‑bucket algorithm implemented with Guava RateLimiter to limit overall QPS.
Example using RateLimiter.acquire():
public class TestRateLimiter { public static void main(String[] args) { RateLimiter limiter = RateLimiter.create(1); for (int i = 0; i < 10; i++) { double wait = limiter.acquire(); System.out.println("Task " + i + " wait " + wait); } System.out.println("Done"); } }Example using tryAcquire with timeout:
public class TestRateLimiter2 { public static void main(String[] args) { RateLimiter limiter = RateLimiter.create(1); for (int i = 0; i < 10; i++) { boolean ok = limiter.tryAcquire(0.5, TimeUnit.SECONDS); System.out.println("Task " + i + " allowed: " + ok); if (!ok) continue; System.out.println("Task " + i + " executing"); } System.out.println("End"); } }2.9 Asynchronous Order Processing
After passing rate limiting and stock validation, push the order to a message queue (e.g., RabbitMQ) for asynchronous handling; successful orders trigger SMS notification, while failures can be retried via compensation mechanisms.
2.10 Service Degradation
When a node crashes, fallback to a standby service (e.g., using Hystrix circuit breaker) to return a friendly message instead of a hard error.
3. Summary
The presented design can sustain several hundred thousand concurrent requests; larger scales (tens of millions) would require further measures such as database sharding, Kafka queues, and larger Redis clusters. The article emphasizes systematic thinking and hands‑on experimentation to master high‑concurrency system design.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
dbaplus Community
Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.
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.
