---
title: "Shopify xử lý 1,27 triệu request/giây trong BFCM"
description: "Bài học system design từ BFCM 2022: phân tán tải, bảo vệ database, dùng cache đúng chỗ và chuẩn bị cho traffic spike."
canonical: "https://tmtuan.dev/vi/articles/shopify-bfcm-risk-mitigation"
language: "vi"
image: "https://tmtuan.dev/_img/articles/shopify-bfcm-risk-mitigation/shopify-bfcm-risk-mitigation-cover.5b694078-og.jpg"
updated: "2026-10-10"
tokens: 3410
---

# Shopify đã xử lý 1,27 triệu request/giây trong Black Friday như thế nào?

Black Friday và Cyber Monday (BFCM) là thời điểm khắc nghiệt nhất của nhiều nền tảng thương mại điện tử. Với cửa hàng, đây là cơ hội tăng doanh số. Với nền tảng vận hành phía sau, đây là bài kiểm tra về khả năng chịu tải trong một khoảng thời gian rất ngắn.

Bài này được biên soạn lại từ bài tổng hợp về BFCM 2022 của Tom Smykowski, xuất bản ngày 2/12/2022. Câu chuyện cho thấy quy mô của bài toán: Shopify phải xử lý khoảng **1,27 triệu request mỗi giây**, tương đương gần 4,3 petabyte dữ liệu truyền tải mỗi ngày. Nhưng con số request không phải toàn bộ câu chuyện. Thử thách lớn hơn là bảo vệ những thành phần có thể trở thành điểm nghẽn, đặc biệt là database, khi hàng triệu người cùng tìm sản phẩm, thêm hàng vào giỏ, checkout và thanh toán.

## 1\. Black Friday là bài kiểm tra sức chịu đựng của hạ tầng

Traffic trong BFCM không chỉ cao mà còn thay đổi rất nhanh. Một chương trình khuyến mãi, một sản phẩm được quan tâm hoặc thời điểm mở bán có thể tạo ra một burst lớn chỉ trong vài giây.

Ở quy mô nền tảng, hệ thống phải giữ được hoạt động cho rất nhiều cửa hàng cùng lúc. Điều đó buộc mọi tầng, từ network, application cho tới data layer, phải được chuẩn bị cho peak traffic thay vì chỉ vận hành tốt ở mức tải trung bình.

Điểm quan trọng là nhìn vào toàn bộ chuỗi xử lý. Thêm năng lực ở một tầng không tự động giải quyết giới hạn ở tầng khác.

## 2\. Database thường là điểm nghẽn khó nhất

Application server có thể scale ngang khá trực tiếp: thêm instance, đặt load balancer phía trước và phân phối request.

```mermaid
flowchart TD
    accTitle: Application layer scale ngang
    accDescr: Load balancer phân phối request đến nhiều application server. Sơ đồ cho thấy application layer có thể mở rộng bằng cách thêm instance.

    LB["Load balancer."] --> APP1["App 1."]
    LB --> APP2["App 2."]
    LB --> APP3["App 3."]

    classDef edge fill:#e8f1ff,stroke:#2563eb,color:#172554,stroke-width:2px;
    classDef app fill:#ecfdf5,stroke:#059669,color:#064e3b,stroke-width:2px;
    class LB edge;
    class APP1,APP2,APP3 app;
```

_Tăng application server giúp mở rộng năng lực xử lý ở application layer, nhưng chưa tự giải quyết giới hạn ở data layer._

Vấn đề xuất hiện khi các application server cùng dồn request xuống một database. Có thể thêm rất nhiều server xử lý business logic, nhưng nếu database không xử lý được số query tương ứng, toàn bộ hệ thống vẫn bị giới hạn tại đó.

```mermaid
flowchart LR
    accTitle: Database bottleneck
    accDescr: Nhiều application server cùng gửi query đến một database. Database trở thành điểm giới hạn khi tổng query vượt năng lực xử lý.

    APP1["App 1."] --> DB[("Database.")]
    APP2["App 2."] --> DB
    APP3["App 3."] --> DB
    APP4["App 4."] --> DB
    APP5["App 5."] --> DB

    classDef app fill:#ecfdf5,stroke:#059669,color:#064e3b,stroke-width:2px;
    classDef data fill:#fff1f2,stroke:#e11d48,color:#881337,stroke-width:3px;
    class APP1,APP2,APP3,APP4,APP5 app;
    class DB data;
```

_Nhiều application server cùng gọi một database có thể biến database thành bottleneck nếu lượng query tăng nhanh hơn khả năng xử lý._

Trong BFCM 2022, fleet MySQL của Shopify xử lý khoảng **14 triệu query mỗi giây**. Con số này nhắc một điều cơ bản trong system design: database, cache, queue và các dependency có trạng thái thường khó mở rộng hơn web tier. Vì vậy, scale không thể chỉ bắt đầu bằng việc tăng số lượng application server.

## 3\. Một triệu request mỗi giây không đi vào một server duy nhất

Không có một server đơn lẻ xử lý toàn bộ 1,27 triệu request mỗi giây. Ở quy mô này, workload được chia qua nhiều tầng, mỗi tầng có một trách nhiệm riêng:

- **Load balancer** phân phối traffic.
- **Application servers** xử lý business logic.
- **Cache services** phục vụ các dữ liệu được đọc lặp lại.
- **Service chuyên biệt** xử lý từng loại workload.
- **Data layer** lưu và xử lý dữ liệu lâu dài.
- **MySQL** nhận các query cần chạm tới dữ liệu có trạng thái.

```mermaid
flowchart TD
    accTitle: Luồng traffic thương mại điện tử mang tính khái niệm
    accDescr: Traffic từ Internet đi tới load balancer và nhóm application server. Dữ liệu được đọc nhiều có thể được phục vụ bởi cache service; dữ liệu cần đọc hoặc ghi đi xuống data layer và MySQL.

    INTERNET["Internet."] --> LB["Load balancer."]
    LB --> APPS["Application servers."]
    APPS --> CACHE["Cache services."]
    APPS --> DATA["Data layer."]
    CACHE --> DATA
    DATA --> MYSQL[("MySQL.")]

    classDef edge fill:#e8f1ff,stroke:#2563eb,color:#172554,stroke-width:2px;
    classDef app fill:#ecfdf5,stroke:#059669,color:#064e3b,stroke-width:2px;
    classDef data fill:#fff1f2,stroke:#e11d48,color:#881337,stroke-width:3px;
    class INTERNET,LB edge;
    class APPS,CACHE app;
    class DATA,MYSQL data;
```

_Sơ đồ khái niệm cho luồng traffic trong bài: cache phục vụ phần đọc lặp lại trước khi request cần đi xuống application và data layer._

Mục tiêu không phải để mọi request đi tới MySQL. Mục tiêu là để chỉ những request thật sự cần dữ liệu gốc hoặc cần thay đổi trạng thái mới đi xuống tầng dữ liệu.

## 4\. Cache là lớp phòng vệ quan trọng

Hãy hình dung một trang sản phẩm đang được đọc một triệu lần nhưng chỉ thay đổi vài lần trong một phút. Nếu mỗi lượt xem đều query database, database phải làm lại cùng một công việc rất nhiều lần.

Cache giải quyết phần lớn tình huống đó:

- **Cache hit:** trả kết quả ngay, không cần query database.
- **Cache miss:** request mới cần đi xuống database để lấy dữ liệu.

Nhờ vậy, cache giúp giảm database CPU, database I/O, network traffic và query latency. Nó cũng giúp hệ thống chịu burst tốt hơn khi nhiều người cùng đọc catalog, thông tin sản phẩm, cấu hình cửa hàng hoặc các dữ liệu ít thay đổi.

Tuy nhiên cache không thay thế database. Những thao tác cần dữ liệu chính xác hoặc tạo thay đổi trạng thái vẫn phải được xử lý cẩn thận ở tầng dữ liệu.

## 5\. Không phải request nào cũng quan trọng như nhau

Một hệ thống chịu tải lớn không thể đối xử mọi request theo cùng một cách.

Những request đọc như xem sản phẩm, tải cấu hình cửa hàng hoặc tải ảnh thường phù hợp với cache hay CDN. Ngược lại, checkout, tạo đơn hàng và thanh toán là thao tác có side effect. Chúng không thể được cache đơn giản như một lượt đọc.

Vì vậy cần phân biệt rõ:

- Read-heavy workload và write-heavy workload.
- Stateless request và state-changing request.
- Tác vụ cần phản hồi ngay và tác vụ có thể xử lý bất đồng bộ.

Việc tách các workload ít quan trọng hoặc có thể trì hoãn giúp dành năng lực cho các luồng cần bảo vệ nhất.

## 6\. Scale không chỉ là tăng server

Giả sử một hệ thống bắt đầu với 10 application server và một database. Tăng lên 100 application server không đem lại nhiều giá trị nếu database vẫn chỉ chịu được một lượng query nhất định.

Scale cần được nhìn theo pipeline, từ client qua CDN và load balancer, tới application, cache, async processing rồi database.

Mỗi tầng cần có năng lực phù hợp với phần việc mà nó nhận. Câu hỏi thiết kế đúng không chỉ là server còn bao nhiêu CPU hoặc RAM, mà là bottleneck tiếp theo nằm ở đâu và cần giảm áp lực cho nó như thế nào.

## 7\. Peak traffic phải được chuẩn bị trước

BFCM có một lợi thế: ngày diễn ra đã biết trước. Điều đó cho phép chuẩn bị capacity planning, load testing, monitoring, alerting, database capacity, infrastructure capacity và disaster recovery từ sớm.

Hệ thống không nên đợi traffic đạt đỉnh rồi mới bắt đầu phản ứng. Chuẩn bị trước tạo cơ hội tìm bottleneck, đặt ngưỡng cảnh báo và kiểm tra những luồng quan trọng trong điều kiện tải cao trước khi sự kiện thật diễn ra.

## 8\. Nguy hiểm nhất là traffic cùng lúc

Một hệ thống có thể xử lý một triệu request mỗi giây ở điều kiện bình thường nhưng vẫn có thể sập khi một triệu request đó xảy ra **cùng một lúc**. Điểm nguy hiểm nằm ở hình dạng của traffic, không chỉ ở tổng số request.

Hãy hình dung một chương trình khuyến mãi bắt đầu đúng lúc **00:00:00**. Ở **23:59:59**, traffic còn thấp. Chỉ một giây sau, rất nhiều người cùng bấm truy cập, làm traffic tăng vọt và cùng dồn vào những tài nguyên giống nhau. Burst đồng thời này có thể nguy hiểm hơn nhiều so với cùng lượng request được phân bố đều theo thời gian.

```mermaid
flowchart LR
    accTitle: Traffic spike khi khuyến mãi bắt đầu
    accDescr: Lúc 23 giờ 59 phút 59 giây traffic thấp. Khi khuyến mãi bắt đầu lúc 00 giờ 00 phút 00 giây, một burst đồng thời đẩy nhiều request tới cùng dependency.

    T1["23:59:59.."] --> LOW["Traffic thấp.."] --> OPEN["Mở bán."] --> T2["00:00:00.."] --> SPIKE["Burst đồng thời..."] --> PRESSURE["Cùng chạm dependency...."]

    classDef calm fill:#ecfdf5,stroke:#059669,color:#064e3b,stroke-width:2px,padding:16px;
    classDef event fill:#e8f1ff,stroke:#2563eb,color:#172554,stroke-width:2px,padding:16px;
    classDef spike fill:#fff7ed,stroke:#ea580c,color:#7c2d12,stroke-width:3px,padding:16px;
    classDef risk fill:#fff1f2,stroke:#e11d48,color:#881337,stroke-width:3px,padding:16px;
    class T1,LOW calm;
    class OPEN,T2 event;
    class SPIKE spike;
    class PRESSURE risk;
```

_Một giây chuyển từ 23:59:59 sang 00:00:00 có thể biến traffic thấp thành burst đồng thời khi khuyến mãi bắt đầu. Đây là bài toán về sự đồng thời, không chỉ là tổng request mỗi giây._

Một ví dụ điển hình là cache vừa hết hạn. Nhiều request cùng cache miss, sau đó cùng query database. Database bị quá tải, latency tăng, request timeout và client bắt đầu retry. Retry lại tạo thêm request, khiến hệ thống rơi vào vòng lặp xấu.

```mermaid
flowchart TD
    accTitle: Vòng lặp quá tải thundering herd
    accDescr: Cache miss xảy ra đồng thời khiến nhiều query đi xuống database. Quá tải làm latency tăng, gây timeout và retry, rồi retry lại tạo thêm request.

    MISS["Cache miss."] --> QUERIES["Nhiều DB query."]
    QUERIES --> OVERLOAD["Database quá tải."]
    OVERLOAD --> LATENCY["Latency tăng."]
    LATENCY --> TIMEOUT["Timeout."]
    TIMEOUT --> RETRY["Retry."]
    RETRY --> QUERIES

    classDef warning fill:#fff7ed,stroke:#ea580c,color:#7c2d12,stroke-width:2px;
    classDef danger fill:#fff1f2,stroke:#e11d48,color:#881337,stroke-width:3px;
    class MISS,QUERIES,LATENCY,TIMEOUT,RETRY warning;
    class OVERLOAD danger;
```

_Một cache miss hàng loạt có thể tạo vòng lặp: query tăng, database quá tải, timeout xuất hiện và retry làm traffic tiếp tục tăng._

Do đó, bài toán không chỉ là đủ capacity. Hệ thống còn cần kiểm soát cách request được phân phối và ngăn hàng triệu request cùng lúc chạm vào một dependency giới hạn.

## 9\. Hệ thống cần biết giảm tải một cách có kiểm soát

Khi traffic vượt quá capacity, hệ thống không nhất thiết chỉ có hai trạng thái: hoạt động hoàn hảo hoặc sập hoàn toàn.

Graceful degradation là khả năng giảm hoặc tạm tắt những tính năng không quan trọng, giới hạn một số loại request, ưu tiên traffic quan trọng nhất và cuối cùng bảo vệ database. Trong thương mại điện tử, giữ checkout và tạo đơn hàng hoạt động thường có giá trị hơn việc duy trì tất cả tính năng phụ ở cùng mức độ.

Mục tiêu của cách tiếp cận này là bảo vệ database và các luồng có side effect, đồng thời duy trì phần quan trọng nhất của trải nghiệm người dùng khi hệ thống chịu áp lực.

## 10\. Bài học có thể áp dụng

Điểm đáng học từ BFCM không chỉ là con số 1,27 triệu request mỗi giây. Đó là cách một hệ thống lớn phân chia workload và không để toàn bộ tải dồn vào cùng một bottleneck.

Khi thiết kế cho traffic cao, hãy:

- Scale ngang application layer khi phù hợp.
- Dùng cache cho dữ liệu đọc nhiều, thay đổi ít.
- Phân biệt rõ read, write, stateless và state-changing workload.
- Bảo vệ database và những dependency khó scale.
- Lập kế hoạch capacity trước peak traffic.
- Theo dõi bottleneck bằng observability, không chỉ CPU và RAM.
- Thiết kế graceful degradation cho tình huống quá tải.

## Kết luận

Câu chuyện BFCM cho thấy scale không đơn giản là thêm server. Scale là xác định điểm nghẽn thực sự, rồi thiết kế để workload không dồn vào điểm nghẽn đó.

Application server có thể scale ngang tương đối dễ. Nhưng database, cache, network, queue và các hệ thống stateful mới thường quyết định giới hạn thực tế. Với Shopify, bài toán còn khó hơn vì phải để hàng triệu merchant tiếp tục vận hành cửa hàng trong thời điểm quan trọng nhất năm. Khi thiết kế cho hàng triệu request, câu hỏi nên bắt đầu là: **bottleneck tiếp theo sẽ nằm ở đâu?**

## Structured data (JSON-LD)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Article","@id":"https://tmtuan.dev/vi/articles/shopify-bfcm-risk-mitigation#article","headline":"Shopify đã xử lý 1,27 triệu request/giây trong Black Friday như thế nào?","description":"Bài học system design từ BFCM 2022: phân tán tải, bảo vệ database, dùng cache đúng chỗ và chuẩn bị cho traffic spike.","datePublished":"2026-10-10","dateModified":"2026-10-10","inLanguage":"vi","url":"https://tmtuan.dev/vi/articles/shopify-bfcm-risk-mitigation","mainEntityOfPage":"https://tmtuan.dev/vi/articles/shopify-bfcm-risk-mitigation","image":"https://tmtuan.dev/_img/articles/shopify-bfcm-risk-mitigation/shopify-bfcm-risk-mitigation-cover.5b694078-og.jpg","author":{"@type":"Person","@id":"https://tmtuan.dev/#person","name":"Tran Manh Tuan","url":"https://tmtuan.dev/en"}},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Trang chủ","item":"https://tmtuan.dev/vi"},{"@type":"ListItem","position":2,"name":"Bài viết","item":"https://tmtuan.dev/vi/articles"},{"@type":"ListItem","position":3,"name":"Shopify đã xử lý 1,27 triệu request/giây trong Black Friday như thế nào?","item":"https://tmtuan.dev/vi/articles/shopify-bfcm-risk-mitigation"}]}]}
```
