Hạ tầng Quy mô Lớn¶
Xây dựng các hệ thống phục vụ hàng triệu người dùng đòi hỏi nhiều hơn một máy chủ đơn. File này bao quát các mẫu mở rộng quy mô, nền tảng hệ thống phân tán, microservices, data pipeline, mở rộng cơ sở dữ liệu, hệ thống tìm kiếm và vector, observability, kỹ thuật độ tin cậy và CI/CD.
- Một mô hình phục vụ 1 yêu cầu mỗi giây có thể chạy trên laptop. Phục vụ 100,000 yêu cầu mỗi giây với độ sẵn sàng 99.9% đòi hỏi hệ thống phân tán, failover tự động và các data pipeline được thiết kế cẩn thận. File này bao quát các mẫu thu hẹp khoảng cách đó.
Khả năng mở rộng (Scalability)¶
-
Vertical scaling (mở rộng theo chiều dọc — scale up): lấy một máy lớn hơn. Nhiều CPU hơn, nhiều RAM hơn, GPU lớn hơn. Đơn giản nhưng có giới hạn cứng (máy lớn nhất có sẵn) và một điểm lỗi duy nhất.
-
Horizontal scaling (mở rộng theo chiều ngang — scale out): thêm nhiều máy hơn. Mỗi cái xử lý một phần lưu lượng. Không có giới hạn máy đơn, nhưng đòi hỏi: cân bằng tải (file 01), phân vùng dữ liệu và xử lý trạng thái phân tán.
-
Các service phi trạng thái (stateless) có thể mở rộng theo chiều ngang theo mặc định. Thêm nhiều instance đằng sau một load balancer. Một model inference server tải trọng số khi khởi động và xử lý các yêu cầu độc lập là stateless — bất kỳ instance nào cũng xử lý được bất kỳ yêu cầu nào.
-
Các service có trạng thái (stateful) (cơ sở dữ liệu, KV-cache, feature store) khó mở rộng hơn. Trạng thái phải được phân vùng qua các máy (sharding, file 01) và replicate để chịu lỗi.
-
Phương trình khả năng mở rộng: với một hệ thống có \(n\) server:
- Lý tưởng: thông lượng mở rộng tuyến tính (\(n\) server → \(n\\times\) thông lượng).
- Thực tế: chi phí từ sự phối hợp, cân bằng tải và truyền dữ liệu nghĩa là thông lượng mở rộng dưới tuyến tính. Định luật Amdahl (chương 13) áp dụng: phần nối tiếp (trạng thái chia sẻ, phối hợp) giới hạn tốc độ tăng.
Hệ thống phân tán¶
-
Một hệ thống phân tán là một nhóm các máy phối hợp để cung cấp một dịch vụ. Các thách thức cơ bản:
-
Phân vùng mạng (Network partitions): các máy không phải lúc nào cũng giao tiếp được. Một cáp mạng bị cắt, một switch hỏng, một trung tâm dữ liệu mất điện. Hệ thống phải xử lý các lỗi một phần.
-
Clock skew (lệch đồng hồ): các máy có các đồng hồ khác nhau. "Sự kiện A xảy ra lúc 10:00:01 trên máy 1" và "Sự kiện B xảy ra lúc 10:00:01 trên máy 2" không có nghĩa chúng xảy ra đồng thời. Logical clocks (bộ đếm Lamport, vector clock) thiết lập thứ tự mà không dựa vào đồng hồ vật lý.
-
Consensus (đồng thuận): làm thế nào nhiều máy thống nhất một giá trị (ví dụ, ai là leader)? Raft là thuật toán đồng thuận tiêu chuẩn. Một cụm các node bầu một leader. Leader xử lý tất cả các ghi. Nếu leader thất bại, các node còn lại bầu một leader mới. Yêu cầu đa số (3 trên 5 node) để hoạt động, nên nó chịu được \(\\lfloor(n-1)/2\\rfloor\) lỗi.
-
Distributed locks (khóa phân tán): đảm bảo chỉ một máy thực hiện một thao tác tới hạn. Redlock (dựa trên Redis) thu thập khóa qua nhiều instance Redis. Nếu đa số instance cấp khóa, nó được thu thập. Dùng cho: ngăn các triển khai mô hình trùng lặp, đảm bảo chỉ một job huấn luyện ghi vào checkpoint.
Microservices¶
- Microservices phân tách một hệ thống thành các service nhỏ, có thể triển khai độc lập. Mỗi service sở hữu một domain:
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ API Gateway │→ │ Feature Svc │→ │ Feature DB │
└─────────────┘ └──────────────┘ └─────────────┘
│
├────────→ ┌──────────────┐ ┌─────────────┐
│ │ Model Svc │→ │ Model Store │
│ └──────────────┘ └─────────────┘
│
└────────→ ┌──────────────┐ ┌─────────────┐
│ Logging Svc │→ │ Log Store │
└──────────────┘ └─────────────┘
-
Ưu điểm: triển khai độc lập (cập nhật model service mà không động vào feature service), mở rộng độc lập (mở rộng model server dựa trên tải yêu cầu, feature server dựa trên tốc độ đọc feature store), tự do công nghệ (model service bằng Python, feature service bằng Go).
-
Nhược điểm: chi phí mạng (mọi cuộc gọi service là một chuyến khứ hồi mạng), độ phức tạp (debug trải dài nhiều service), tính nhất quán dữ liệu (không có giao dịch cross-service).
-
Service discovery (khám phá service): API gateway tìm model service như thế nào? Các tùy chọn: dựa trên DNS (mỗi service đăng ký một tên DNS), K8s services (tích hợp sẵn), hoặc một service registry (Consul, Eureka).
-
Saga pattern: cho các thao tác trải dài nhiều service (tạo người dùng + cấp phát tài nguyên + gửi email chào mừng), dùng một saga: một chuỗi các giao dịch cục bộ với các hành động bù trừ nếu bất kỳ bước nào thất bại.
Data Pipelines¶
- Các hệ thống ML tiêu thụ lượng dữ liệu khổng lồ. Data pipelines di chuyển, biến đổi và phục vụ dữ liệu này:
Xử lý theo lô (Batch Processing)¶
-
Xử lý khối lượng lớn dữ liệu ở các khoảng thời gian đều đặn (hàng giờ, hàng ngày).
-
MapReduce: mô hình lô nguyên thủy. Map (biến đổi mỗi bản ghi độc lập) → Shuffle (nhóm theo khóa) → Reduce (tổng hợp theo từng nhóm). Về mặt khái niệm đơn giản nhưng dài dòng khi triển khai.
-
Apache Spark: công cụ batch hiện đại. Xử lý in-memory (nhanh gấp 100x MapReduce cho các thuật toán lặp). Hỗ trợ SQL, DataFrames và ML pipeline. Tiêu chuẩn cho feature engineering quy mô lớn.
-
Ví dụ: tính các đặc trưng người dùng cho một hệ thống gợi ý. Đầu vào: 1B sự kiện hoạt động người dùng từ 30 ngày qua. Đầu ra: 100M vector đặc trưng người dùng. Chạy hàng ngày như một Spark job, đầu ra tới feature store.
Xử lý luồng (Stream Processing)¶
-
Xử lý dữ liệu theo thời gian thực khi nó đến (độ trễ dưới giây).
-
Apache Flink: công cụ xử lý luồng hàng đầu. Xử lý exactly-once, xử lý event-time (xử lý các sự kiện theo thời điểm chúng xảy ra, không phải khi chúng đến), windowing (tumbling, sliding, session windows).
-
Kafka Streams: xử lý luồng nhẹ được tích hợp trong Kafka. Tốt cho các biến đổi đơn giản (lọc, tổng hợp) mà không triển khai một cụm riêng.
-
Ví dụ: phát hiện gian lận thời gian thực. Mỗi giao dịch thẻ tín dụng là một sự kiện Kafka. Một Flink job tính các thống kê đang chạy (tần suất giao dịch, thay đổi vị trí) và gắn cờ các bất thường trong 100ms.
Kiến trúc Lambda¶
-
Kết hợp xử lý lô và luồng. Batch layer cung cấp các kết quả chính xác, toàn diện (nhưng với độ trễ). Speed layer cung cấp các kết quả xấp xỉ, thời gian thực. Một serving layer hợp nhất cả hai.
-
Trong thực tế, nhiều đội hiện dùng kiến trúc Kappa: chỉ xử lý luồng, coi luồng như nguồn sự thật. Luồng có thể phát lại (Kafka giữ lại các sự kiện), nên lô có thể được mô phỏng bằng cách phát lại luồng.
Hạ tầng Huấn luyện ML¶
- Huấn luyện một mô hình tiền tuyến (100B+ tham số) là một bài toán hạ tầng quy mô lớn: hàng nghìn GPU chạy trong nhiều tháng, tiêu thụ hàng megawatt điện, tạo ra hàng petabyte dữ liệu và tốn hàng chục triệu đô la. Hạ tầng quyết định huấn luyện thành công hay thất bại.
Cụm GPU¶
- Một cụm huấn luyện là một tập hợp các server GPU được kết nối bởi các mạng tốc độ cao. Các thành phần chính:
-
Các server GPU (node): mỗi server có 4-8 GPU. Cấu hình điển hình: 8 × H100 GPU, 2 × AMD EPYC CPU, 2 TB RAM, 30 TB NVMe SSD. Các GPU trong một node được kết nối bởi NVLink (900 GB/s mỗi GPU trên H100), nhanh gấp 30x so với PCIe.
-
Kích thước cụm: một cụm huấn luyện nhỏ có 64-256 GPU (8-32 node). Một cụm huấn luyện mô hình tiền tuyến có 4,000-32,000 GPU (500-4000 node). Llama 3 của Meta dùng 16,384 H100 GPU. Google huấn luyện trên các TPU pod với 8,000+ chip.
-
Tính nhẩm (Back-of-envelope): huấn luyện một mô hình 70B đòi hỏi ~\(2M tính toán. Huấn luyện một mô hình tiền tuyến 400B+ đòi hỏi ~\)50-100M. Phần cứng cụm tự nó tốn ~\(500M-\)1B ở giá H100 ($30K mỗi GPU × 16,000 GPU = $480M).
Topology Mạng¶
-
Mạng giữa các node GPU là thành phần hạ tầng quan trọng nhất. Nếu các GPU không thể trao đổi gradient đủ nhanh, chúng sẽ rảnh rỗi chờ giao tiếp hoàn tất.
-
InfiniBand là tiêu chuẩn cho mạng cụm GPU. Quantum-2 InfiniBand của NVIDIA cung cấp 400 Gb/s mỗi cổng. Mỗi node thường có 8 cổng InfiniBand (một cho mỗi GPU), cho tổng băng thông bisection 400 GB/s mỗi node.
-
RDMA (Remote Direct Memory Access — Truy cập bộ nhớ trực tiếp từ xa): InfiniBand hỗ trợ RDMA, truyền dữ liệu trực tiếp giữa bộ nhớ GPU trên các node khác nhau mà không liên quan đến CPU. Điều này giảm độ trễ từ ~100μs (TCP) xuống ~1μs và là thiết yếu cho all-reduce gradient hiệu quả (chương 6).
-
Network topology quan trọng: một fat tree (mạng Clos) cung cấp băng thông bisection đầy đủ (bất kỳ GPU nào cũng có thể giao tiếp với bất kỳ GPU nào khác ở tốc độ đầy đủ). Các topology rẻ hơn (rail-optimised, 3D torus) cung cấp ít băng thông hơn nhưng rẻ hơn. Topology phải khớp với chiến lược song song:
- Data parallelism: all-reduce qua tất cả các GPU → cần băng thông bisection cao (fat tree).
- Tensor parallelism: giao tiếp trong một node → NVLink xử lý việc này (không cần mạng).
- Pipeline parallelism: giao tiếp giữa các stage pipeline kề nhau → chỉ cần băng thông giữa các cặp node cụ thể (rail-optimised là ổn).
-
Các thay thế Ethernet: RoCE v2 (RDMA over Converged Ethernet) cung cấp RDMA qua hạ tầng Ethernet tiêu chuẩn. Rẻ hơn InfiniBand nhưng với độ trễ cao hơn và tắc nghẽn hơn. Google dùng RoCE cho một số mạng TPU pod. Ultra Ethernet Consortium đang phát triển Ethernet không mất gói cho các khối lượng AI.
Lưu trữ cho Huấn luyện¶
-
Huấn luyện đòi hỏi ba tầng lưu trữ:
-
Dataset storage: kho ngữ liệu huấn luyện (1-100 TB văn bản, hoặc petabyte dữ liệu đa phương thức). Lưu trong các hệ thống tệp phân tán hoặc lưu trữ đối tượng. Phải hỗ trợ đọc tuần tự thông lượng cao (data loader đọc dữ liệu trong các lô lớn). Lustre và GPFS là các hệ thống tệp HPC phổ biến; các thay thế cloud bao gồm FSx for Lustre (AWS) và Filestore (GCP).
-
Checkpoint storage: trạng thái huấn luyện (trọng số mô hình + trạng thái bộ tối ưu + trạng thái scheduler) được lưu định kỳ. Cho một mô hình 70B ở mixed precision với bộ tối ưu Adam: ~560 GB mỗi checkpoint (70B × 4 byte × 2 cho bộ tối ưu). Lưu mỗi giờ cho một lượt chạy 3 tháng = ~2000 checkpoint = 1.1 PB. Trong thực tế, chỉ giữ N checkpoint mới nhất, và xóa các cái cũ. Phải đủ nhanh để checkpoint không làm chậm đáng kể huấn luyện.
-
Logging và metrics: dữ liệu theo dõi thí nghiệm (đường cong loss, lịch trình learning rate, norm gradient). Tương đối nhỏ nhưng phải được ghi theo thời gian thực. W&B, MLflow hoặc TensorBoard xử lý việc này.
-
-
Điểm thắt lưu trữ: một cụm 16,000 GPU tải một lô huấn luyện cần đọc ~100 GB/s dữ liệu liên tục. Nếu hệ thống tệp không duy trì được thông lượng này, các GPU rảnh rỗi chờ dữ liệu. Tối ưu data pipeline (prefetching, caching, tối ưu định dạng dùng WebDataset hoặc Mosaic Streaming) là then chốt.
Lập lịch Job (Job Scheduling)¶
-
Một cụm GPU phục vụ nhiều đội và dự án. Một job scheduler cấp phát GPU cho các job huấn luyện:
-
SLURM: scheduler job HPC tiêu chuẩn. Người dùng gửi các job chỉ định số lượng GPU, bộ nhớ và giới hạn thời gian. SLURM cấp phát tài nguyên và quản lý hàng đợi. Hỗ trợ lập lịch dựa trên ưu tiên, preemption và phân bổ fair-share giữa các đội.
-
Kubernetes với GPU scheduling (chương 18 file 02): cách tiếp cận cloud-native. Các GPU device plugin của K8s phơi bày GPU như các tài nguyên có thể lập lịch. Volcano và Run:ai thêm các tính năng lập lịch đặc thù cho ML: gang scheduling (cấp phát tất cả GPU cho một job cùng một lúc, không phải từng cái một), hàng đợi ưu tiên và GPU time-sharing.
-
Các thách thức lập lịch:
- Fragmentation (phân mảnh): một cụm với 1000 GPU có thể có 200 free, nhưng trải rải trên 50 node (4 free mỗi node). Một job cần 128 GPU liền kề không thể chạy, ngay cả khi có đủ tổng số GPU. Defragmentation (di chuyển các job để gộp các GPU free) hoặc topology-aware scheduling (cấp phát các GPU được kết nối tốt) giải quyết việc này.
- Ưu tiên và preemption: các thí nghiệm khẩn cấp nên preempt các job có ưu tiên thấp hơn. Nhưng preempt một job huấn luyện đã chạy 2 ngày lãng phí tính toán. Scheduler phải cân bằng ưu tiên với hiệu quả.
- Fair share: các đội nên nhận phần tính toán được phân bổ của họ theo thời gian, ngay cả khi một đội gửi nhiều job hơn phần của nó.
Chịu lỗi (Fault Tolerance)¶
-
Ở quy mô hàng nghìn GPU chạy trong nhiều tháng, các lỗi phần cứng không phải ngoại lệ — chúng là thường lệ. Thời gian trung bình giữa các lỗi cho một cụm 16,000 GPU được tính bằng giờ, không phải tháng.
-
Các lỗi thường gặp: lỗi bộ nhớ GPU (ECC-correctable và uncorrectable), lỗi NVLink (giao tiếp GPU-to-GPU trong một node), lỗi liên kết InfiniBand (giao tiếp node-to-node), sập node (kernel panic, lỗi PSU) và lỗi lưu trữ (đĩa hoặc bộ điều khiển hỏng).
-
Checkpointing là phòng thủ chính. Lưu toàn bộ trạng thái huấn luyện (mô hình, bộ tối ưu, vị trí data loader) mỗi N bước. Khi lỗi: xác định node lỗi, thay thế hoặc loại bỏ nó, khởi động lại huấn luyện từ checkpoint mới nhất. Chi phí của một lỗi là tính toán giữa lần checkpoint cuối và lỗi.
-
Sự đánh đổi tần suất checkpoint: checkpoint thường xuyên (mỗi 10 phút) lãng phí ít tính toán hơn khi lỗi nhưng làm chậm huấn luyện (checkpoint 560 GB mất thời gian). Checkpoint không thường xuyên (mỗi 2 giờ) nhanh hơn nhưng lãng phí tới 2 giờ tính toán khi lỗi. Hầu hết các đội checkpoint mỗi 20-60 phút.
-
Elastic training (huấn luyện đàn hồi): các framework hiện đại (PyTorch Elastic, DeepSpeed) hỗ trợ thay đổi kích thước lượt chạy huấn luyện mà không khởi động lại. Nếu 2 node trong 500 lỗi, huấn luyện tiếp tục với 498 node. Các node lỗi được thay thế, và huấn luyện tự động kết hợp chúng khi chúng trực tuyến lại.
-
Health monitoring (giám sát sức khỏe): giám sát liên tục tất cả GPU (nhiệt độ, lỗi bộ nhớ, thông lượng tính toán), các liên kết mạng (mất gói, độ trễ) và lưu trữ (thông lượng, tỷ lệ lỗi). Cảnh báo tự động khi có bất thường. Một số cụm chạy các kiểm tra sức khỏe GPU định kỳ (một bài kiểm tra tính toán ngắn) để chủ động xác định phần cứng đang suy thoái trước khi nó lỗi.
-
Ở quy mô: huấn luyện Llama 3 của Meta (16,384 H100, 54 ngày) trải qua ~466 lần gián đoạn job. Thời gian huấn luyện hiệu quả chỉ là ~90% thời gian đồng hồ tường — 10% bị mất vào lỗi và phục hồi. Hạ tầng để đạt được 90% (thay vì 50% hay 70%) là thứ tách biệt các tổ chức có thể huấn luyện mô hình tiền tuyến khỏi những tổ chức không thể.
Chi phí và Hiệu quả¶
- Chi phí hạ tầng huấn luyện bị chi phối bởi GPU hours:
| Thành phần | % Tổng chi phí |
|---|---|
| GPU compute | 70-80% |
| Mạng (InfiniBand) | 10-15% |
| Lưu trữ | 5-10% |
| Làm mát và điện | 5-10% |
-
GPU utilisation (Model FLOPs Utilisation — MFU) đo lường phần nào của hiệu năng đỉnh lý thuyết của GPU thực sự được dùng cho tính toán hữu ích. Đỉnh H100 là 989 TFLOPS (FP8). Đạt 40-50% MFU là tốt; 50-60% là xuất sắc. Khoảng cách là do: chi phí giao tiếp (all-reduce, pipeline bubbles), các giới hạn băng thông bộ nhớ và thời gian rảnh trong khi checkpoint và tải dữ liệu.
-
Cải thiện MFU: chồng lấp tính toán và giao tiếp (chương 6), dùng attention hiệu quả (Flash Attention, chương 16), tối ưu tải dữ liệu (ngăn GPU đói), giảm chi phí checkpoint (async checkpointing, checkpoint vào NVMe nhanh trước, sau đó background-copy sang lưu trữ bền vững).
-
Build vs buy (tự xây vs mua): ở quy mô nhỏ (<256 GPU), cloud rẻ hơn (không chi phí upfront, trả theo giờ). Ở quy mô lớn (>1000 GPU, dùng liên tục 6+ tháng), sở hữu phần cứng rẻ hơn (~thấp hơn 2-3x TCO trong 3 năm). Hầu hết các công ty AI dùng kết hợp: các cụm sở hữu cho huấn luyện liên tục, cloud cho dung lượng burst và thử nghiệm.
Mở rộng Cơ sở dữ liệu¶
-
Read replicas (bản sao đọc): định tuyến các truy vấn đọc tới các replica của cơ sở dữ liệu chính. Primary xử lý các ghi, các replica xử lý các đọc. Vì hầu hết khối lượng là nặng đọc (95%+ đọc), điều này mở rộng thông lượng đọc tuyến tính với số lượng replica.
-
Partitioning (sharding, từ file 01): chia dữ liệu qua nhiều cơ sở dữ liệu. Mỗi phân vùng độc lập, cho phép đọc và ghi song song. Thách thức là các truy vấn cross-partition (join dữ liệu từ các shard khác nhau).
-
Connection pooling: các cơ sở dữ liệu có dung lượng kết nối giới hạn. Một connection pool (PgBouncer cho PostgreSQL) tái sử dụng các kết nối qua các yêu cầu, ngăn cạn kiệt kết nối khi hàng trăm instance service mỗi cái cố gắng kết nối.
Hệ thống Tìm kiếm và Vector¶
Tìm kiếm Văn bản¶
-
Inverted index (chỉ mục đảo): nền tảng của tìm kiếm văn bản. Với mỗi từ, lưu một danh sách các tài liệu chứa từ đó. Một truy vấn giao các danh sách cho mỗi từ truy vấn. Elasticsearch là tiêu chuẩn: phân tán, thời gian thực, hỗ trợ tìm kiếm toàn văn, aggregation và truy vấn không gian địa lý.
-
BM25: hàm chấm điểm truy xuất văn bản tiêu chuẩn. Chấm điểm tài liệu bằng tần suất từ, nghịch đảo tần suất tài liệu và chuẩn hóa độ dài tài liệu. Đơn giản nhưng hiệu quả — vẫn cạnh tranh với các phương pháp neural cho các truy vấn nặng từ khóa.
Tìm kiếm Vector¶
-
Vector databases lưu các embedding (các vector nhiều chiều) và hỗ trợ tìm kiếm láng giềng gần xấp xỉ (ANN) nhanh. Cho một embedding truy vấn, tìm \(k\) embedding đã lưu tương tự nhất.
-
FAISS (Facebook AI Similarity Search): một thư viện (không phải cơ sở dữ liệu) cho tìm kiếm ANN. Hỗ trợ nhiều loại index:
- Flat: tìm kiếm chính xác, \(O(n)\). Dùng cho tập dữ liệu nhỏ hoặc làm ground truth.
- IVF (Inverted File): phân vùng các vector thành các cụm, chỉ tìm kiếm các cụm gần nhất. \(O(n/k)\) mỗi truy vấn.
- HNSW (Hierarchical Navigable Small World): dựa trên đồ thị. Xây một đồ thị phân cấp, điều hướng từ thô đến tinh. Cực nhanh và chính xác, lựa chọn mặc định cho hầu hết ứng dụng.
- Product Quantisation (PQ): nén các vector thành các mã compact để tìm kiếm tiết kiệm bộ nhớ. Đánh đổi độ chính xác lấy bộ nhớ.
-
Các vector database được quản lý: Pinecone, Weaviate, Milvus, Qdrant. Chúng xử lý việc mở rộng, replicate và cập nhật thời gian thực mà FAISS không làm.
-
Cho RAG (Retrieval-Augmented Generation — Tạo sinh có truy hồi tăng cường): truy vấn người dùng → embed với một text encoder → tìm kiếm vector database cho các tài liệu liên quan → đặt trước các tài liệu được truy hồi vào prompt của LLM. Chất lượng của truy hồi quyết định trực tiếp chất lượng phản hồi của LLM.
Observability¶
- Observability là khả năng hiểu what đang xảy ra bên trong hệ thống của bạn từ các đầu ra bên ngoài của nó. Ba trụ cột:
Logging¶
-
Structured logs (log có cấu trúc — JSON) có thể tìm kiếm và phân tích. Các log không có cấu trúc ("ERROR: something failed") thì không. Luôn log: timestamp, tên service, request ID (để trace qua các service), mức độ nghiêm trọng và ngữ cảnh liên quan.
-
ELK stack (Elasticsearch, Logstash, Kibana): pipeline log tiêu chuẩn. Logstash thu thập và biến đổi các log, Elasticsearch lập chỉ mục chúng, Kibana trực quan hóa và tìm kiếm.
Metrics¶
-
Metrics là các phép đo số học theo thời gian: tốc độ yêu cầu, tỷ lệ lỗi, percentiles độ trễ, GPU utilisation, độ sâu hàng đợi. Prometheus scrape các metric từ các service; Grafana trực quan hóa chúng trong các dashboard với cảnh báo.
-
Phương pháp RED cho các service: Rate (yêu cầu/giây), Errors (tỷ lệ lỗi), Duration (độ trễ). Giám sát những thứ này cho mọi service.
-
Phương pháp USE cho các tài nguyên: Utilisation (% đang dùng), Saturation (độ sâu hàng đợi), Errors. Giám sát những thứ này cho mọi tài nguyên (CPU, GPU, bộ nhớ, đĩa, mạng).
Tracing¶
-
Distributed tracing (trace phân tán) theo dõi một yêu cầu đơn lẻ qua nhiều service. Một yêu cầu người dùng gõ API gateway → feature service → model service → postprocessing. Một trace ghi lại thời gian của mỗi bước nhảy, cho thấy độ trễ được tiêu ở đâu.
-
OpenTelemetry: tiêu chuẩn mở cho traces, metrics và logs. Công cụ mã của bạn một lần, xuất ra bất kỳ backend nào (Jaeger, Zipkin, Datadog).
Độ tin cậy (Reliability)¶
-
SLO (Service Level Objective): độ tin cậy mục tiêu. "99.9% các yêu cầu hoàn thành trong <200ms." Điều này cho một error budget cụ thể: 0.1% các yêu cầu (khoảng 43 phút mỗi tháng) có thể chậm hoặc thất bại.
-
SLI (Service Level Indicator): phép đo. "Độ trễ phân vị 99 trong 5 phút qua."
-
SLA (Service Level Agreement): lời hứa hợp đồng với hậu quả. "Nếu độ sẵn sàng giảm dưới 99.95%, khách hàng được hoàn tiền."
-
Error budgets (ngân sách lỗi): nếu SLO của bạn là 99.9% và bạn đang ở 99.99%, bạn có ngân sách cho các thay đổi rủi ro (triển khai một mô hình mới, di chuyển cơ sở dữ liệu). Nếu bạn ở 99.85%, đóng băng mọi thay đổi và tập trung vào độ tin cậy. Error budgets biến độ tin cậy từ một mục tiêu trừu tượng thành một tài nguyên có thể đo lường.
-
Chaos engineering (kỹ thuật hỗn loạn): cố ý tiêm các lỗi (giết một server, thêm độ trễ mạng, làm hỏng dữ liệu) để kiểm tra xem hệ thống của bạn xử lý chúng đúng không. Chaos Monkey của Netflix ngẫu nhiên chấm dứt các instance production. Nếu hệ thống vẫn đứng vững, nó có khả năng phục hồi. Nếu nó sập, bạn đã tìm thấy một bug trước khi người dùng của mình làm.
CI/CD¶
-
Continuous Integration (Tích hợp liên tục): tự động xây dựng và kiểm tra mọi thay đổi mã. Mọi push kích hoạt: lint, type check, unit tests, integration tests. Nếu bất kỳ cái nào thất bại, thay đổi bị từ chối. Điều này bắt các bug trước khi chúng đến production.
-
Continuous Deployment (Triển khai liên tục): tự động triển khai các thay đổi vượt qua CI. Các chiến lược triển khai:
- Blue-green: chạy hai môi trường giống hệt nhau (blue = hiện tại, green = mới). Chuyển lưu lượng từ blue sang green ngay lập tức. Nếu green thất bại, chuyển lại blue (rollback tức thì).
- Canary: định tuyến một phần nhỏ lưu lượng (1-5%) tới phiên bản mới. Giám sát các lỗi. Tăng dần lưu lượng nếu các metric trông ổn. Điều này giới hạn bán kính vụ nổ của một triển khai tệ.
- Feature flags: triển khai mã mới nhưng ẩn nó đằng sau một cờ. Bật cờ cho một tập hợp con người dùng (người test nội bộ, sau đó người dùng beta, rồi mọi người). Tách triển khai (mã sống) khỏi phát hành (người dùng thấy tính năng).
-
Cho ML: CI/CD bao gồm các bước đặc thù cho mô hình. Một thay đổi mô hình kích hoạt: unit tests (shape tests, gradient checks), đánh giá trên một tập held-out (độ chính xác không được thoái hóa), shadow deployment (chạy mô hình mới cạnh mô hình cũ, so sánh đầu ra) và rollout dần dần (canary từ 1% → 100%).