I. Phòng bệnh hơn chữa bệnh
Thay vì đợi nó tìm đến mình thì mình chuẩn bị trước để cho nó không đến, mà nếu có đến thì mình cũng đã có kịch bản cho xử lý cho nó:
- Xây dựng hệ thống log, monitor: giúp phát hiện vấn đề sớm, cho phép can thiệp trước khi vấn đề trở nên nghiêm trọng. Như hệ thống mình làm thì sài Prometheus, Datadog và CloudWatch.
- Xây dựng hệ thống có khả năng scale up dựa trên metrics: là một chiến lược hiệu quả để đối phó với tải tăng đột biến.
- Phân phối tải: Giúp các service được chia đề công việc hơn, tránh nghẽn cổ chai ở 1 điểm. Mình sài AWS thì có một số service hỗ trợ việc này, có thể kể đến như:
- API Gateway: quản lý các yêu cầu HTTP và WebSocket đến các service.
- ELB: có khả năng phân phối lưu lượng đến nhiều instance EC2 hoặc container.
- Route 53: là dịch vụ DNS, cũng có khả năng phân phối tải, dựa trên các chính sách như trọng số, địa lý, latency, giúp bạn định tuyến lưu lượng đến các endpoint khác nhau dựa trên các tiêu chí cụ thể.
II. Khi mắc bệnh
Nâng cấp phần cứng (Vertical horizontal) và scale up horizontal là giải pháp nhanh chóng và hiệu quả trong ngắn hạn. Tuy nhiên, đây chỉ là giải pháp tạm thời, ngay sau đó phải bắt tay vào truy tìm gốc rễ của vấn đề.
- Phân tích logs và metrics để xác định chính xác điểm thắt cổ chai.
- Sử dụng công cụ giám sát và profiling để hiểu rõ vấn đề.
III. Quy tắc 5 whys
Mình thường áp dụng phương pháp phân tích "5 Whys", mục tiêu là để xác định nguyên nhân gốc rễ của một vấn đề bằng cách hỏi "Tại sao?" năm lần liên tiếp. Mỗi câu trả lời sẽ hình thành cơ sở cho câu hỏi tiếp theo. Đây là các bước cơ bản:
- Xác định vấn đề cụ thể.
- Hỏi tại sao vấn đề xảy ra và ghi lại câu trả lời.
- Nếu câu trả lời không xác định nguyên nhân gốc rễ của vấn đề, hãy hỏi "Tại sao?" một lần nữa.
- Lặp lại quá trình này ít nhất năm lần hoặc cho đến khi xác định được nguyên nhân gốc rễ.
Ví dụ về việc áp dụng 5 Whys trong vấn đề về nghẽn cổ chai ở database:
- Tại sao hệ thống bị nghẽn cổ chai ở database?
- Vì database đang phải xử lý một lượng lớn các thao tác đọc và ghi đồng thời, vượt quá khả năng xử lý bình thường.
- Tại sao database phải xử lý quá nhiều thao tác đọc và ghi đồng thời?
- Vì hệ thống vừa thực hiện một sự kiện cập nhật dữ liệu lớn, trong khi vẫn phải xử lý các yêu cầu thông thường từ người dùng.
- Tại sao sự kiện cập nhật dữ liệu lớn lại diễn ra vào thời điểm này?
- Vì một cronjob được lập lịch để chạy vào giờ cao điểm, thực hiện cập nhật hàng loạt lên database.
- Tại sao việc cập nhật hàng loạt lại gây ra tải lớn như vậy?
- Vì mỗi cập nhật kích hoạt nhiều database triggers, thực hiện các tác vụ business logic phức tạp trực tiếp trong database.
- Tại sao lại có quá nhiều triggers thực hiện business logic trong database?
- Vì trong giai đoạn đầu phát triển, team ưu tiên tốc độ triển khai tính năng mà chưa xem xét đến hiệu suất dài hạn và khả năng mở rộng của hệ thống.
Nguyên nhân gốc rễ: Thiếu quy trình đánh giá hiệu suất và khả năng mở rộng trong quá trình phát triển ban đầu, dẫn đến việc lạm dụng database triggers và lập lịch không hợp lý cho các tác vụ nặng.
Giải pháp:
- Tối ưu hóa lịch chạy cronjob: Lập lịch lại cronjob vào thời điểm có ít traffic hơn. Xem xét việc chia nhỏ tác vụ cập nhật lớn thành nhiều tác vụ nhỏ hơn.
- Đánh giá lại việc sử dụng triggers: Chuyển bớt logic xử lý từ triggers sang application layer. Tối ưu hóa các triggers hiện có để giảm tải cho database.
- Cải thiện kiến trúc hệ thống: Xem xét việc áp dụng CQRS để tách biệt read và write operations.
Bằng cách sử dụng 5 Whys, chúng ta đã đi từ một triệu chứng bề mặt "nghẽn cổ chai" đến nguyên nhân gốc rễ (xây dựng hệ thống thiếu khả năng mở rộng) và có thể đề xuất các giải pháp toàn diện hơn thay vì chỉ giải quyết vấn đề tức thời.