Học cách tư duy performance và tìm bottleneck trong hệ thống phân tán. Hiểu về scalability dimensions, throughput vs latency, vertical vs horizontal scaling, và quy trình xác định điểm nghẽn thực tế.
Chia sẻ bài học
Khi hệ thống bắt đầu chậm, nhiều developer nghĩ ngay: "Thêm server!". Nhưng đây là sai lầm phổ biến nhất trong system design.
Scaling không phải là thêm resource. Scaling là tìm và loại bỏ bottleneck.
Nếu bạn không biết đâu là điểm nghẽn, việc thêm server chỉ là lãng phí tiền. Đôi khi thêm 10 server vẫn không giải quyết được vấn đề vì bottleneck nằm ở database, không phải application server.
Lesson này dạy bạn tư duy performance từ góc nhìn architect - cách nhìn hệ thống như một pipeline, tìm điểm nghẽn, và quyết định đúng cách scale.
Trước khi học CDN, caching, database sharding... bạn cần hiểu:
Mỗi kỹ thuật scale đều giải quyết một loại bottleneck cụ thể.
Nếu không biết tìm bottleneck, bạn sẽ áp dụng giải pháp sai → lãng phí effort + tiền bạc.
Mental model đúng:
Không phải: nghe người ta dùng Redis → mình cũng dùng Redis.
Khi nói về performance, hệ thống có 3 chiều bạn phải quan tâm:
Đây là khả năng xử lý của server - tính toán, logic, algorithms.
Bottleneck ở compute khi:
Giải pháp:
Khả năng đọc/ghi dữ liệu và lượng data bạn cần lưu.
Bottleneck ở storage khi:
Giải pháp:
Tốc độ truyền tải dữ liệu giữa các component.
Bottleneck ở network khi:
Giải pháp:
flowchart TB
subgraph Compute
CPU[CPU Usage]
Logic[Business Logic]
end
subgraph Storage
Disk[Disk I/O]
Data[Data Volume]
end
subgraph Network
BW[Bandwidth]
Latency[Geographic Latency]
end
System[System Performance] --> Compute
System --> Storage
System --> Network
Bottleneck có thể nằm ở bất kỳ dimension nào. Task của architect là tìm ra dimension nào đang limit hệ thống.
Khi measure performance, có 2 metrics bạn phải hiểu rõ:
Throughput = số lượng request hệ thống xử lý được trong 1 giây.
Ví dụ:
Throughput cao = hệ thống xử lý được nhiều traffic.
Latency = thời gian để hoàn thành 1 request.
Ví dụ:
Latency thấp = user experience tốt.
Đây là điểm khó: không phải lúc nào cũng optimize được cả hai.
Case 1: Tăng throughput → có thể tăng latency
Khi bạn cho phép API xử lý nhiều request cùng lúc (tăng concurrency), mỗi request có thể phải chờ lâu hơn vì resource bị share.
Trước: 100 req/s, latency 50ms
Sau: 500 req/s, latency 200ms
Throughput tăng 5x, nhưng latency tăng 4x.
Case 2: Giảm latency → có thể giảm throughput
Khi bạn optimize từng request chạy nhanh hơn (giảm latency), có thể phải giảm số request xử lý đồng thời.
Architect decision:
Bạn phải biết business cần gì để quyết định optimize direction.
Nâng cấp server hiện tại: CPU mạnh hơn, RAM nhiều hơn, disk nhanh hơn.
Ưu điểm:
Nhược điểm:
Khi nào dùng vertical scaling:
Thêm nhiều server cùng xử lý: 1 server → 5 servers → 50 servers.
Ưu điểm:
Nhược điểm:
Khi nào dùng horizontal scaling:
flowchart LR
subgraph Vertical["Vertical Scaling"]
V1[Small Server] -->|Upgrade| V2[Bigger Server]
end
subgraph Horizontal["Horizontal Scaling"]
H1[Server 1]
H2[Server 2]
H3[Server 3]
LB[Load Balancer] --> H1
LB --> H2
LB --> H3
end
Reality: Hầu hết hệ thống lớn dùng cả hai - vertical cho database, horizontal cho application layer.
Amdahl's Law nói rằng: Speedup của hệ thống bị giới hạn bởi phần không thể parallelize.
Giả sử một request có flow:
Total time: 100ms
Khi bạn scale horizontal:
Total time: 55ms (chỉ cải thiện 1.8x, không phải 2x)
Serialize response chính là bottleneck. Dù bạn thêm bao nhiêu server, step này vẫn giữ nguyên.
Practical insight:
Khi bạn scale và không thấy improvement tuyến tính → tìm phần không parallel được (serialization, critical section, single-threaded logic).
Architect thinking: Không phải cứ thêm server là hệ thống nhanh hơn. Bạn phải tìm phần nào đang block parallel execution.
Đây là quy trình thực tế architect dùng để tìm bottleneck:
Trước khi tìm bottleneck, phải biết target là gì.
Không rõ ràng:
Rõ ràng:
Không có goal = không biết đâu là bottleneck.
Đo tất cả metrics quan trọng:
Application layer:
Database layer:
Network:
Tool: Prometheus, Grafana, DataDog, New Relic, CloudWatch.
Nhìn vào metrics → tìm component nào đang maxed out.
Ví dụ thực tế:
API server: CPU 40%, Memory 50% → OK
Load balancer: CPU 10% → OK
Database: CPU 95%, query time 500ms → BOTTLENECK!
→ Bottleneck ở database, không phải API server.
Thêm API server sẽ không giải quyết vấn đề.
Tìm được bottleneck chưa đủ. Phải hiểu tại sao nó bottleneck.
Database CPU cao có thể vì:
Phải dig deeper để biết giải pháp đúng.
Mỗi root cause có giải pháp khác nhau:
| Root Cause | Solution |
|---|---|
| Missing index | Add index |
| N+1 query | Query optimization, eager loading |
| High read load | Read replica, caching |
| High write load | Sharding, queue async writes |
| Large dataset | Archiving, partitioning |
Không có one-size-fits-all solution.
Sau khi apply solution:
Performance optimization là iterative process.
flowchart TD
A[Define Goal] --> B[Measure Current State]
B --> C[Identify Constraint]
C --> D[Understand Root Cause]
D --> E[Pick Solution]
E --> F[Test & Measure]
F -->|New Bottleneck| C
F -->|Goal Met| G[Done]
Đừng đợi đến khi production down mới tìm bottleneck.
Load testing = simulate traffic để expose bottleneck sớm.
1. Baseline test
2. Stress test
3. Spike test
4. Soak test (Endurance test)
Ví dụ k6 script:
import http from 'k6/http';
import { check, sleep } from 'k6';
export let options = {
stages: [
{ duration: '2m', target: 100 }, // ramp up
{ duration: '5m', target: 100 }, // stay at 100 users
{ duration: '2m', target: 200 }, // ramp to 200
{ duration: '5m', target: 200 },
{ duration: '2m', target: 0 }, // ramp down
],
};
export default function () {
let res = http.get('https://api.example.com/users');
check(res, { 'status was 200': (r) => r.status == 200 });
sleep(1);
}
Quan sát metrics khi load tăng:
Đó chính là bottleneck.
Ghi nhớ mental model này:
Scaling không phải là thêm resource ngẫu nhiên.
Scaling = identify bottleneck → remove bottleneck → repeat.
Hệ thống như một pipeline. Water flow bị limit bởi đoạn ống nhỏ nhất.
[Wide pipe] → [NARROW PIPE] → [Wide pipe]
↑
Bottleneck
Dù bạn mở rộng 2 đoạn pipe to ra, water flow vẫn bị limit bởi đoạn giữa.
Apply vào system:
[API: 10k req/s] → [DB: 1k req/s] → [Response]
↑
Bottleneck
Thêm API server không giúp gì. Phải scale database hoặc thêm cache.
Architect mindset:
1. Scalability có 3 dimensions: Compute, Storage, Network
Bottleneck có thể nằm ở bất kỳ dimension nào. Phải identify đúng.
2. Throughput ≠ Latency
Hai metrics khác nhau, có thể conflict. Biết business cần gì để optimize đúng direction.
3. Vertical scaling: đơn giản nhưng có limit. Horizontal scaling: unlimited nhưng phức tạp
Hầu hết hệ thống lớn dùng hybrid approach.
4. Amdahl's Law: Speedup bị giới hạn bởi phần không parallel được
Tìm critical section, serialization point là key.
5. Bottleneck identification process:
Define goal → Measure → Identify constraint → Root cause → Solution → Test lại.
6. Load testing giúp tìm bottleneck trước production
Stress test, spike test, soak test đều quan trọng.
7. Mental model: Scale = Remove bottleneck
Không phải add resource. Là tìm và loại bỏ constraint.
Hãy nhớ: Architect giỏi không phải người biết nhiều công nghệ. Là người biết tìm đúng bottleneck và pick đúng giải pháp.