[Series: Tư duy bứt phá] Phần 3: Bức tranh lớn - Rời mắt khỏi IDE để nhìn vào System Architecture
Ở Phần 2, chúng ta đã đập tan ảo tưởng về "Happy Path" và đối mặt với sự tàn khốc của môi trường Production. Bây giờ, giả sử bạn đã biết cách handle edge cases, biết tối ưu query, biết dùng Cache. Nhưng hệ thống vẫn... "toang" khi scale lên.
Lý do? Vì bạn vẫn đang giải quyết bài toán ở cấp độ "Micro" (những dòng code, những function riêng lẻ) mà bỏ quên góc nhìn "Macro" (Bức tranh tổng thể của hệ thống). Hôm nay, hãy tạm gập IDE lại. Chúng ta sẽ nói về System Architecture.
1. 2 giờ "vẽ vời" cứu rỗi 2 tuần OT (Overtime)
Nhận ticket xong, mở ngay IDE lên gõ lạch cạch là một cơn nghiện khó cai của Thợ gõ. Cảm giác màn hình console chạy chữ liên tục thật ngầu, giống hệt các hacker trên phim. Nhưng thực tế phũ phàng là: Code càng nhanh, đập đi viết lại càng lẹ.
Kỹ sư phần mềm hiếm khi mở editor ngay lập tức. Công cụ đầu tiên họ mở ra là Draw.io, Excalidraw, hoặc chỉ đơn giản là một tờ giấy và cây bút.
- Họ vẽ cái gì? Họ vẽ Data Flow (luồng dữ liệu đi từ đâu đến đâu), Sequence Diagram (thứ tự gọi API giữa các service), và Entity Relationship (cấu trúc database).
- Tại sao phải vẽ? Vì sửa một sai lầm trên bản vẽ kiến trúc mất 5 phút di chuột. Sửa một sai lầm trong kiến trúc khi code đã merge vào nhánh
maincó thể mất hàng tuần OT rớt nước mắt, kèm theo nguy cơ downtime hệ thống.
2. Bước ra khỏi vùng an toàn của Framework
Thợ gõ thường tự đóng khung mình vào một ngôn ngữ hoặc framework nhất định. Họ giải quyết mọi bài toán bằng công cụ duy nhất họ có trên tay. Nếu họ rành Laravel, mọi logic từ routing, queue, đến background job đều nhồi hết vào con Monolith PHP đó.
Kỹ sư nhìn hệ thống như một bộ xếp hình (Lego), và ngôn ngữ/framework chỉ là một trong những mảnh ghép.
Hãy lấy một Case Study xương máu: Tích hợp cổng thanh toán (ZaloPay/VNPay). Hệ thống của bạn có một luồng nhận Webhook (IPN) từ cổng thanh toán báo về khi user chuyển khoản thành công.
- Cách làm "thuần tuý": Cổng thanh toán gọi API -> Server (ví dụ chạy PHP/Laravel) nhận request -> Chạy logic update trạng thái đơn hàng trong DB -> Trả về HTTP 200. Ngày bình thường, mọi thứ êm đẹp.
- Lúc có biến: Đến ngày sale mùng 9/9, hàng chục ngàn đơn hàng thanh toán thành công cùng lúc. Cổng thanh toán "bắn" Webhook về dồn dập. Server xử lý không kịp, Database bị lock, API phản hồi chậm (timeout). Cổng thanh toán tưởng server bạn lỗi nên tiếp tục retry bắn lại webhook. Hiệu ứng hòn tuyết lăn (Snowball effect) xảy ra và hệ thống... sập toàn tập.
Kỹ sư giải bài toán này bằng Kiến trúc (Architecture) chứ không bằng Code: Họ nhận ra HTTP Server không sinh ra để chịu tải dồn dập (burst traffic). Họ thiết kế lại luồng: API nhận Webhook chỉ làm đúng một việc cực nhẹ: Ném cục payload đó vào một Message Queue (như Kafka hoặc RabbitMQ) rồi trả về 200 ngay lập tức. Phía sau Queue, họ dựng một con worker viết bằng Golang (tận dụng Goroutine xử lý concurrency cực tốt) để từ từ "ăn" (consume) đống message đó và update vào Database theo tốc độ mà DB chịu được.
Đó chính là tư duy kiến trúc: Biết chia nhỏ trách nhiệm và chọn đúng vũ khí cho từng điểm nóng.
3. Nghệ thuật của sự Đánh đổi (Trade-off)
Đây là cảnh giới cao nhất của System Architecture. Trong lập trình, không có "Viên đạn bạc" (Silver Bullet) nào giải quyết được mọi vấn đề. Mọi quyết định kiến trúc đều là một sự đánh đổi.
- Bạn muốn làm Microservices? Tuyệt vời, từng team có thể deploy độc lập, hệ thống dễ scale. Nhưng bù lại, bạn phải đối mặt với cơn ác mộng debug phân tán (Distributed Tracing), độ trễ mạng (Network Latency) giữa các service, và việc quản lý transaction phức tạp lên gấp chục lần.
- Bạn thích Local-First Architecture? UX sẽ cực mượt vì app chạy không cần mạng. Nhưng "cái giá phải trả" là logic đồng bộ (Sync) dữ liệu siêu phức tạp khi mạng có lại, phải xử lý conflict (xung đột dữ liệu) nếu nhiều thiết bị cùng sửa một record.
- Dùng NoSQL (MongoDB) hay RDBMS (PostgreSQL)? Dùng NoSQL thì schema linh hoạt, insert nhanh, nhưng đánh đổi lại tính nhất quán dữ liệu (Consistency) kém hơn, viết join query cực kỳ đau đầu.
Thợ gõ hay cãi nhau xem công nghệ nào là "Best Practice". Kỹ sư hiểu rằng chữ "Best" phụ thuộc vào bài toán hiện tại. Nhiệm vụ của họ là phân tích cái giá phải trả của mỗi giải pháp, và chọn phương án ít "đau" nhất cho dự án.
Tạm kết
Đứng trước một bài toán lớn, hãy tập thói quen lùi lại một bước. Đừng vội đâm đầu vào những file logic chi chít. Hãy nhìn xem dữ liệu đang chảy qua những thành phần nào, chỗ nào là nút thắt cổ chai (bottleneck), và nếu một service "chết lâm sàng", phần còn lại của hệ thống có sống sót nổi không.
Khi bạn bắt đầu nhìn hệ thống dưới dạng những khối block tương tác với nhau thay vì những dòng code chạy tuần tự, bạn đã chính thức bước một chân qua cánh cửa của System Architecture.
Nhưng dù kiến trúc có xịn sò cỡ nào, Kafka có chạy nhanh ra sao, tất cả sẽ vô nghĩa nếu thứ bạn xây ra không giải quyết được vấn đề của User. Ở Phần 4, chúng ta sẽ bàn về "Kỹ năng mềm" tối thượng của hệ thống cứng: Thấu hiểu Domain Business.
All rights reserved