T
Trinh Digital
Xây dựng Hệ thống

CDN + Load Balancing: Website chịu 100,000 concurrent users trong flash sale

Trinh Digital · · 8 phút đọc

Case study load balancing này ghi lại cách chúng tôi giúp một website e-commerce chịu được 100.000 concurrent users trong đợt flash sale — từ kiến trúc chỉ chịu được 5.000 users. Không downtime, không mất đơn hàng, và ROI gấp 15 lần chi phí đầu tư.

Bối cảnh

Khách hàng: Sàn TMĐT thời trang, thị trường Việt Nam.

Vấn đề: Mỗi đợt flash sale (1 lần/tháng), website sập trong 5 phút đầu tiên. Lần gần nhất (flash sale 11/11):

  • 70.000 users truy cập đồng thời
  • Website sập hoàn toàn lúc 0h02
  • Mất 3 giờ để khôi phục
  • Thiệt hại ước tính: 1.2 tỉ VND doanh thu + mất uy tín

Hệ thống cũ:

  • 1 VPS (8GB RAM, 4 vCPU)
  • Nginx + PHP-FPM + MySQL trên cùng 1 server
  • Không CDN, không caching layer
  • Capacity: ~5.000 concurrent users

Yêu cầu: Xây dựng hệ thống chịu 100.000 concurrent users cho đợt flash sale 12/12, trong vòng 3 tuần.

Thiết kế kiến trúc mới

Nguyên tắc thiết kế

  1. Scale horizontally: Thêm server thay vì nâng cấp server
  2. Stateless application: Không lưu state trên app server
  3. Cache everything possible: Giảm tải database
  4. Graceful degradation: Nếu quá tải, giảm tính năng thay vì sập hoàn toàn

Kiến trúc tổng thể

Users

Cloudflare CDN (300+ PoPs)
  ↓ (DDoS protection + static cache)
Load Balancer (HAProxy)
  ├── App Server 1 (Nginx + PHP-FPM)
  ├── App Server 2 (Nginx + PHP-FPM)
  ├── App Server 3 (Nginx + PHP-FPM)
  └── App Server 4 (chỉ bật khi flash sale)

  Redis Cluster (Session + Cache)

  MySQL Primary → MySQL Replica (read)

Chi tiết từng tầng

Tầng 1: Cloudflare CDN + WAF

Chức năngCấu hình
Cache static filesẢnh, CSS, JS, fonts — TTL 30 ngày
Cache HTMLTrang chủ, category — TTL 5 phút
DDoS protectionAuto, sensitivity: Medium
Rate limiting100 requests/phút cho /checkout
WAFBlock SQL injection, XSS
Waiting RoomKích hoạt khi > 80.000 concurrent

Cloudflare Waiting Room: Tính năng “phòng chờ” — khi traffic vượt ngưỡng, users mới phải xếp hàng, không làm sập server.

Tầng 2: HAProxy Load Balancer

# /etc/haproxy/haproxy.cfg
frontend http-in
    bind *:80
    bind *:443 ssl crt /etc/ssl/cert.pem
    default_backend app_servers

backend app_servers
    balance roundrobin
    option httpchk GET /health
    server app1 10.0.0.1:80 check weight 100
    server app2 10.0.0.2:80 check weight 100
    server app3 10.0.0.3:80 check weight 100
    server app4 10.0.0.4:80 check weight 50  # Flash sale only
Thuật toánMô tảUse case
Round RobinChia đều requestDefault, app servers cùng cấu hình
Least ConnectionsGửi đến server ít kết nối nhấtKhi requests có thời gian xử lý khác nhau
IP HashCùng IP luôn đến cùng serverSession sticky (không cần nếu có Redis)
WeightedServer mạnh nhận nhiều hơnApp servers khác cấu hình

Tầng 3: Application Servers

Mỗi app server (4GB RAM, 2 vCPU):

  • Nginx + PHP 8.3 FPM
  • Stateless — session lưu trên Redis, không lưu local
  • OPcache enabled
  • PHP worker processes: 50

Tầng 4: Redis Cluster

  • Redis 1 (4GB RAM): Session storage + Object cache
  • Redis 2 (2GB RAM): Queue (đơn hàng chờ xử lý)

Flash sale optimization:

# Pre-warm cache trước 1 giờ
# Cache tất cả sản phẩm flash sale vào Redis
redis-cli SET product:1234 '{"name":"...", "price":199000, "stock":500}'
redis-cli SET product:1234:stock 500  # Atomic counter cho tồn kho

Tầng 5: Database

  • MySQL Primary (16GB RAM, 8 vCPU): Write operations
  • MySQL Replica (8GB RAM, 4 vCPU): Read operations (listing, search)
  • Read/Write split qua application code

Chiến lược flash sale

Pre-sale (trước 24 giờ)

  1. Bật app server 4 (reserve server)
  2. Pre-warm cache: Load tất cả sản phẩm flash sale vào Redis
  3. Pre-generate static pages: Trang chủ, landing page flash sale
  4. Scale database connections: Tăng max_connections
  5. Alert team: Monitoring heightened alerting

During sale (0h00 – 2h00)

  1. Cloudflare Waiting Room kích hoạt khi > 80.000 concurrent
  2. Tồn kho quản lý qua Redis (atomic decrement, không query MySQL cho mỗi đơn)
  3. Order queue: Đơn hàng đẩy vào Redis queue, xử lý async
  4. Disable non-essential features: Tắt related products, reviews, analytics tracking

Post-sale

  1. Tắt app server 4 (tiết kiệm chi phí)
  2. Process order queue (đơn hàng chờ trong Redis)
  3. Sync inventory (Redis → MySQL)
  4. Generate reports

Kết quả flash sale 12/12

Traffic

MetricFlash sale cũ (11/11)Flash sale mới (12/12)
Peak concurrent users70.000 (sập)105.000
Requests/giây (peak)15.000 (sập)45.000
Uptime0% (3 giờ sập)100%
Avg response time (peak)N/A (sập)280ms
Error rate100%0.02%

Business

Metric11/11 (cũ)12/12 (mới)Thay đổi
Revenue (đêm flash sale)~200M VND (trước khi sập)2.8 tỉ VND+1300%
Đơn hàng2.500 (trước khi sập)18.500+640%
Conversion rateN/A4.2%
Customer complaints500+12-98%

Chi phí hạ tầng

Hạng mụcHàng tháng (thường)Flash sale (thêm)
3 App servers (4GB)3.6 triệu VND
1 App server (reserve)0200.000 VND (2 ngày)
Load balancer (HAProxy)600.000 VND
Redis cluster (2 instances)1.2 triệu VND
MySQL Primary2.4 triệu VND
MySQL Replica1.2 triệu VND
Cloudflare Pro500.000 VND
Tổng9.5 triệu VND/tháng+200.000 VND

So sánh:

  • Hệ thống cũ: 1.5 triệu VND/tháng + thiệt hại 1.2 tỉ VND/flash sale
  • Hệ thống mới: 9.5 triệu VND/tháng + doanh thu 2.8 tỉ VND/flash sale
  • ROI: 295x chi phí tăng thêm

Bài học kinh nghiệm

1. Đừng đợi sập mới scale

Lên kế hoạch capacity trước 2–4 tuần. Load test trước flash sale ít nhất 1 tuần. Chi phí chuẩn bị trước luôn rẻ hơn chi phí khắc phục sự cố.

2. Stateless application là bắt buộc

Nếu session lưu trên app server, không thể load balance. Chuyển session sang Redis/Memcached để bất kỳ server nào cũng xử lý được bất kỳ request nào.

3. Cache là vũ khí số 1

Database là bottleneck #1 khi traffic tăng. Cache 90% read operations vào Redis → database chỉ xử lý writes → chịu được traffic gấp 10x.

4. Graceful degradation > crash

Khi quá tải, tắt features không quan trọng (reviews, related products, analytics) thay vì để website sập hoàn toàn. Waiting room cho phép kiểm soát traffic thay vì bị overwhelm.

5. Monitor real-time trong sự kiện

Trong flash sale, cần dashboard real-time hiển thị:

  • Concurrent users, requests/giây
  • Response time, error rate
  • CPU, RAM, disk I/O mỗi server
  • Redis memory, hit rate
  • MySQL connections, slow queries
  • Order count, revenue

FAQ — Câu hỏi thường gặp

Load balancing có cần cho website nhỏ không?

Chưa cần nếu traffic < 10.000 visitors/ngày. Nhưng nên thiết kế stateless từ đầu (session trên Redis) để dễ dàng thêm load balancing khi cần. Chi phí setup stateless từ đầu: gần 0. Chi phí refactor sau: 10–30 triệu VND.

HAProxy vs Nginx Load Balancer — dùng cái nào?

Cả hai đều tốt. HAProxy chuyên về load balancing, có health checks tốt hơn. Nginx đa dụng hơn (vừa web server vừa load balancer). Nếu đã dùng Nginx: dùng Nginx upstream. Nếu cần load balancer riêng: HAProxy. Hoặc dùng Cloudflare Load Balancing (managed, không cần tự quản lý).

Kết luận

100.000 concurrent users không phải con số “enterprise only” — với kiến trúc đúng (CDN + Load Balancer + Redis + DB replica), chi phí chỉ ~10 triệu VND/tháng. Quan trọng nhất là thiết kế kiến trúc đúng từ đầu và chuẩn bị trước cho peak traffic.

Nếu bạn đang lên kế hoạch flash sale hoặc cần xây dựng hệ thống có khả năng scale cho doanh nghiệp, hãy liên hệ Trinh Digital để được tư vấn kiến trúc phù hợp.

#scalability#CDN#case study#load balancing
Chia sẻ: Z

Sẵn sàng chuyển đổi số cùng Trinh Digital?

Liên hệ ngay để nhận tư vấn miễn phí. Đội ngũ chuyên gia sẽ phân tích nhu cầu và đề xuất giải pháp tối ưu.

Zalo