Hàng triệu phiếu bầu trong năm phút, không mất phiếu nào.
Go, Kafka, Redis và PostgreSQL giữ phiếu bầu chính xác và đẩy điểm số tới hàng triệu màn hình.
Mô phỏng ZADD và ZREVRANGE với dữ liệu giả lập, không phải số liệu thật.
Không phải một ứng dụng CRUD
Yên tĩnh cả tuần, rồi hàng triệu request ập đến ngay khi MC mở cổng. Bốn ràng buộc quyết định toàn bộ kiến trúc.
Lưu lượng bùng nổ
Tăng giảm theo CPU là quá chậm. Hệ thống phải mở rộng theo hàng đợi, và tắt hẳn khi không có sự kiện.
Đa khách thuê
Mỗi chiến dịch có thí sinh, luật điểm và subdomain mặc định dưới vinhcancode.vn. Về sau có thể gắn tên miền riêng, giống cách Shopify làm. Dữ liệu cuộc thi A không được lọt sang B.
Lũy đẳng
Webhook VNPay, Momo, PayOS có thể bị gửi lại nhiều lần. Mỗi mã giao dịch chỉ xử lý đúng một lần.
Bảng xếp hạng nhảy điểm tức thì
Không cần F5. Mỗi phiếu hợp lệ phải đẩy điểm mới tới hàng triệu kết nối WebSocket mà không cạn RAM máy chủ.
Bốn thách thức, bốn chiến lược
Mỗi lựa chọn kiến trúc phía sau đều bắt nguồn từ một nút thắt cổ chai cụ thể.
Bão INSERT làm nghẽn cơ sở dữ liệuhàng đợi và ghi theo lô+
Vấn đề
Mỗi lệnh INSERT đi qua Parser, Planner, Executor rồi ghi WAL. Khi 100.000 người bấm trong cùng một giây, hồ chứa kết nối cạn kiệt và CPU chạm 100%.
Chiến lược
API chỉ ghi sự kiện vào hàng đợi rồi báo thành công ngay. Worker gom lô và nạp bằng COPY: 10.000 dòng trong 10 đến 30 ms, nhanh gấp hàng trăm lần INSERT.
ORDER BY vắt kiệt CPU khi xếp hạngcơ sở dữ liệu trên RAM+
Vấn đề
Mỗi lần mở bảng xếp hạng lại chạy ORDER BY score DESC LIMIT 100. Hàng triệu người xem cùng lúc sẽ làm sập máy chủ cơ sở dữ liệu.
Chiến lược
Đưa logic sắp xếp sang cơ sở dữ liệu in-memory với Sorted Set. Điểm cập nhật thẳng vào RAM, truy xuất Top 100 chưa tới 1 ms và không chạm vào cơ sở dữ liệu lõi.
Hàng triệu WebSocket ngốn cạn RAMproxy phân phối chuyên biệt+
Vấn đề
Bài toán C1M: một kết nối nhàn rỗi vẫn sinh gói ping/pong. Nếu API tự giữ 1 triệu kết nối, RAM tiêu tốn từ hàng chục tới hàng trăm GB.
Chiến lược
Tách hẳn một proxy Pub/Sub viết bằng Go, chỉ tốn 30 đến 50 KB RAM mỗi kết nối và gom nhịp tim. API gửi một tín hiệu, proxy fan-out xuống mọi màn hình.
Auto-scaling theo CPU quá chậmmở rộng theo sự kiện+
Vấn đề
Khi CPU chạm 80% thì hệ thống đã quá tải, hàng đợi nghẽn và request timeout. Chờ 2 đến 3 phút để khởi động máy mới là quá muộn.
Chiến lược
Hỏi hàng đợi thay vì hỏi CPU: còn bao nhiêu phiếu chưa xử lý (Consumer Lag). Worker nhân bản chủ động khi lag tăng và về 0 khi hàng đợi trống.
Bảy lớp, mỗi lớp một nhiệm vụ
Phiếu bầu ghi qua Kafka vào PostgreSQL. Điểm số tính trên Redis rồi đẩy xuống trình duyệt qua Centrifugo.
Luồng ghi: bảo vệ từng phiếu
EVALSHA để chặn bot.HMAC_SHA256, khóa phân tán bằng SETNX. Trùng giao dịch vẫn trả 200 OK để cổng thanh toán ngừng gửi lại, rồi đẩy sự kiện vào Kafka.COPY nhị phân qua pgx. Nhanh gấp 100 đến 200 lần INSERT, khoảng 10 đến 30 ms mỗi lô.Luồng đọc: điểm số tới khán giả
ZADD khi có phiếu mới, ZREVRANGE lấy Top 100 trong micro-giây.client.batch_periodic_events và websocket.process_commands_off_read_loop cho hàng triệu kết nối nhàn rỗi.Điều phối: mở rộng đúng lúc
Sáu cái bẫy dù đã chọn đúng công nghệ
Công cụ mạnh vẫn có thể làm sập đêm chung kết nếu ghép sai. Chọn một bẫy để xem cách tránh.
AWS thay phần cứng, không thay kiến trúc
Worker Go vẫn phải gom lô, vẫn phải COPY, vẫn phải SET LOCAL. Cloud chỉ gánh việc vận hành hạ tầng.
Hai thành phần phải tự chạy trên Amazon EKS
KEDA: Auto Scaling mặc định đo CPU nên chỉ phản ứng khi đã quá tải. KEDA đọc Consumer Lag từ MSK và còn scale về 0.
Centrifugo: API Gateway WebSockets tính phí theo tin nhắn và số phút kết nối. Một triệu khán giả trong ba giờ có thể tốn hàng chục nghìn USD cho một đêm.
Đọc trực tiếp tài liệu gốc
Tám file markdown trong thư mục documents, mở ngay tại trang này bằng giao diện đọc riêng.