How to Build a High‑Performance Flash Sale (Seckill) System: Architecture, Challenges & Solutions
This article analyzes the business flow, technical challenges, and architectural design of a flash‑sale (seckill) system, offering practical solutions for isolation, high‑concurrency handling, database sharding, caching, cheating prevention, and data consistency to ensure reliable high‑traffic e‑commerce operations.
1 Seckill Business Analysis
Normal e‑commerce flow: query product → create order → deduct inventory → update order → payment → seller ships.
Seckill characteristics: low price, massive promotion, instant sell‑out, timed launch, short duration, and extremely high concurrent requests.
2 Seckill Technical Challenges
Running a seckill together with the normal site can overload application and database servers; a single product with 10,000 expected participants can generate 10,000 concurrent requests.
Impact on existing services – isolate seckill in a separate domain or sub‑domain.
Application & DB load – static product page, no DB hit before the start.
Network & bandwidth – a 200 KB page ×10,000 = 2 GB/s, requiring CDN and extra ISP bandwidth.
Direct order URL – make the URL dynamic with a server‑side token.
Buy button activation – gray before start, bright after start, controlled by a small JavaScript file.
Only the first successful order is sent to the order subsystem; later requests see a “sale ended” page.
Pre‑order checks – limit per‑server request count and global order count.
3 Seckill Architecture Principles
Intercept as many requests as possible upstream, use cache heavily (read‑many/write‑few), and keep the seckill service independent from the normal e‑commerce flow.
4 Seckill Architecture Design
4.1 Front‑end layer
Static product page with a countdown timer, served from CDN; JavaScript polls a lightweight time‑sync API.
4.2 Site layer
Rate‑limit per UID and per item, cache identical responses for a short window.
4.3 Service layer
Pre‑process requests, drop those when inventory is exhausted, queue the rest for asynchronous processing.
4.4 Database layer
Use an ArrayBlockingQueue to hold potential successful orders and apply optimistic locking to avoid over‑selling.
Database sharding (range, hash, router service) and grouping (master‑slave) improve availability and scalability.
Read‑through cache (Redis/Memcached) reduces DB load; write‑through with delayed cache eviction avoids stale data.
update auction_auctions set
quantity = #inQuantity#
where auction_id = #itemId# and quantity = #dbQuantity# package seckill;
import org.apache.http.HttpRequest;
/**
* 预处理阶段,把不必要的请求直接驳回,必要的请求添加到队列中进入下一阶段.
*/
public class PreProcessor {
// 商品是否还有剩余
private static boolean reminds = true;
private static void forbidden() {
// Do something.
}
public static boolean checkReminds() {
if (reminds) {
// 远程检测是否还有剩余,该RPC接口应由数据库服务器提供,不必完全严格检查.
if (!RPC.checkReminds()) {
reminds = false;
}
}
return reminds;
}
/**
* 每一个HTTP请求都要经过该预处理.
*/
public static void preProcess(HttpRequest request) {
if (checkReminds()) {
// 一个并发的队列
RequestQueue.queue.add(request);
} else {
// 如果已经没有商品了,则直接驳回请求即可.
forbidden();
}
}
} package seckill;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.http.HttpRequest;
public class RequestQueue {
public static ConcurrentLinkedQueue<HttpRequest> queue = new ConcurrentLinkedQueue<HttpRequest>();
} package seckill;
import org.apache.http.HttpRequest;
public class Processor {
/**
* 发送秒杀事务到数据库队列.
*/
public static void kill(BidInfo info) {
DB.bids.add(info);
}
public static void process() {
BidInfo info = new BidInfo(RequestQueue.queue.poll());
if (info != null) {
kill(info);
}
}
}
class BidInfo {
BidInfo(HttpRequest request) {
// Do something.
}
} package seckill;
import java.util.concurrent.ArrayBlockingQueue;
public class DB {
public static int count = 10;
public static ArrayBlockingQueue<BidInfo> bids = new ArrayBlockingQueue<BidInfo>(10);
public static boolean checkReminds() {
// TODO
return true;
}
// 单线程操作
public static void bid() {
BidInfo info = bids.poll();
while (count-- > 0) {
// insert into table Bids values(item_id, user_id, bid_date, other)
// select count(id) from Bids where item_id = ?
// 如果数据库商品数量大约总数,则标志秒杀已完成,设置标志位reminds = false.
info = bids.poll();
}
}
}5 High‑Concurrency Challenges
QPS calculation, response‑time growth, overload protection at the CGI/NGINX layer, graceful degradation, and traffic‑shaping to avoid “snowball” failures.
6 Cheating: Attack & Defense
Multiple requests from one account – allow only one request per account (Redis flag or queue).
Zombie accounts – rate‑limit per IP, captcha, or block IP.
IP rotation – hard to distinguish; use business thresholds or data‑mining to filter.
7 Data Safety Under High Concurrency
Over‑selling occurs when many threads read the same remaining stock. Solutions include pessimistic lock (slow), FIFO queue (memory pressure), and optimistic lock with version number (Redis WATCH) to ensure only one successful purchase.
8 Summary
Flash‑sale systems require isolation, static assets, CDN, request throttling, queue‑based order processing, sharded databases, cache, and robust consistency mechanisms to survive tens of thousands of concurrent users while preventing cheating and over‑selling.
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.
21CTO
21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.
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.
