Hai Lỗi - nói dối e blog

Hai Lỗi

Hai lỗi “đáng nhớ đời” Hôm nay mình vừa phát hiện hai lỗi hệ thống đều thuộc dạng kinh điển, đáng ghi vào “sổ tay phòng tránh sự cố”. Xin chia sẻ lại để đồng nghiệp cảnh giác.

Lỗi đầu tiên liên quan đến cơ chế lưu trữ dữ liệu của server biên tập. Chúng ta sử dụng phương pháp ghi dồn tiếp vào file dữ liệu để đảm bảo không mất mát thông tin, đồng thời xây dựng file index riêng để đánh dấu vị trí offset của phiên bản dữ liệu mới nhất trong file chính, giúp tăng tốc độ tra cứu. Vấn đề nằm ở việc khi thiết kế, mặc dù đã lường trước khả năng file dữ liệu vượt ngưỡng 4GB, nhưng do sơ suất đã dùng kiểu dữ liệu 32bit thay vì 64bit để lưu offset. Sau thời gian dài vận hành, hiện tượng tràn số nguyên终于 xảy ra khiến file index bị hỏng hoàn toàn. Dù hệ quả không quá nghiêm trọng (chỉ cần rebuild lại index), nhưng đây là bài học lớn về việc xem nhẹ việc quy hoạch không gian lưu trữ.

Lỗi thứ hai xuất phát từ cải tiến quy trình khởi tạo engine client gần đây. Vì module OpenGL bắt buộc phải có cửa sổ trước khi khởi động, mà việc tạo cửa sổ lại phụ thuộc vào logic nghiệp vụ. Trước đây thiết kế chưa tối ưu (cần quá nhiều thao tác can thiệp thủ công). Để tăng tính đóng gói và tự động hóa, mình áp dụng giải pháp tạo cửa sổ giả lập trước khi người dùng định nghĩa cửa sổ thực, sau đó giao tiếp OpenGL được thiết lập sẵn. Đến khi người dùng tạo cửa sổ tùy chỉnh, hệ thống sẽ tự động thay thế cửa sổ giả bằng cửa sổ thật. Tuy nhiên do thiếu sót, việc hủy bỏ cửa sổ giả đã kéo theo việc xóa luôn context OpenGL. Phương án đúng đắn phải là: Cho phép hủy cửa sổ giả nhưng phải giữ nguyên context OpenGL, sau đó chuyển bối cảnh làm việc sang cửa sổ mới. Vấn đề tưởng đơn giản nhưng ẩn giấu rất sâu, mãi đến hôm nay mới lộ diện khi mình test tạo các đối tượng OpenGL trước khi dựng cửa sổ người dùng. Vì các handle OpenGL đều là kiểu số nguyên, nên khi tạo context mới, các handle cũ “tái sinh” khiến chương trình không crash nhưng hiển thị sai lệch. Đây là lời nhắc nhở quan trọng về việc xử lý các tài nguyên hệ thống cần độ chính xác tuyệt đối.

Qua hai sự cố trên, chúng ta cần rút ra ba bài học xương máu:

  1. Luôn tính toán quy mô hệ thống ở mức độ cao nhất có thể
  2. Khi thiết kế module phụ thuộc lẫn nhau phải xác định rõ trách nhiệm từng lớp
  3. Các handle hệ thống không nên tự ý hủy-bỏ ngầm mà cần cơ chế release rõ ràng
0%