Hệ thống 22/09/2026 5 phút

Rò rỉ file descriptor: vì sao app chạy tốt vài giờ rồi chết vì "Too many open files"

App chạy ổn lúc đầu rồi bỗng crash sau vài giờ với 'Too many open files'? Gần như luôn là rò rỉ file descriptor — mở file/socket mà quên đóng. Bài này chạy thật: mô phỏng rò rỉ đến khi chạm ulimit và nhận Errno 24, so với bản dùng with (fd phẳng lì ở 4), và cách đếm fd qua /proc/pid/fd để phát hiện sớm.

Lập trình Go 22/09/2026 10 phút

Livelock và starvation trong Go: khi goroutine bận rộn mà không tiến, hoặc bị bỏ đói

Deadlock làm mọi goroutine đứng; livelock làm chúng bận rộn mà không tiến; starvation bỏ đói số ít. Đo thật: mẫu nhường nhau hiếm khi livelock trên runtime Go (1,03x lãng phí), nhưng starvation lộ 12x mất cân bằng dù Go mutex chống đói hoàn toàn. Cách phát hiện và tránh. Go 1.23.

Lập trình 22/09/2026 6 phút

Schema evolution: thêm field mà không làm sập dịch vụ đang chạy phiên bản cũ

Trong hệ phân tán, code cũ và mới chạy song song lúc triển khai — dữ liệu phải đọc chéo được cả hai chiều. Bài này chạy thật bằng Protobuf: code mới ghi 4 field, code cũ đọc vẫn lấy được 2 field và bỏ qua field lạ không crash; code cũ ghi 2 field, code mới đọc field mới nhận default. Và một cái bẫy đo được: đổi kiểu field làm mất dữ liệu âm thầm. Kèm luật an toàn vs nguy hiểm.

Lập trình 22/09/2026 6 phút

MessagePack: JSON nhị phân — nhưng đo thật cho thấy nó không nhỏ như bạn tưởng

MessagePack được quảng cáo là JSON nhị phân gọn hơn. Đúng, nhưng đo thật cho con số khiêm tốn hơn kỳ vọng: cùng một đơn hàng, MessagePack mặc định chỉ nhỏ hơn JSON 1,08 lần, bật compact ints được 1,25 lần — còn xa Protobuf (~2 lần). Lý do lộ ra khi nhìn byte: MessagePack vẫn lưu tên field trong map. Điểm mạnh thật của nó là giải mã nhanh ~2,4 lần JSON và đổi đúng một dòng code.

Lập trình Go 22/09/2026 9 phút

Continuous profiling trong Go: hồ sơ CPU/bộ nhớ từ dịch vụ đang chạy thật

Benchmark cục bộ chỉ đo cái bạn nghĩ là nóng; điểm nóng production thường ở chỗ bất ngờ với tải và dữ liệu thật. net/http/pprof phơi endpoint để thu hồ sơ từ dịch vụ đang chạy mà không dừng nó. Đo thật trong Go: thu CPU profile 3 giây từ service live, pprof chỉ đúng hàm nóng 100% CPU.

Lập trình 22/09/2026 6 phút

Index B-tree: vì sao tạo index rồi vẫn Seq Scan — bẫy non-sargable và cách viết query cho đúng

Bạn tạo index nhưng query vẫn chậm và EXPLAIN vẫn báo Seq Scan? Vì predicate không sargable — chỉ cần bọc cột trong một hàm là index nằm im vô dụng. Bài này đo thật trên bảng 1 triệu dòng: WHERE email=x dùng index (0.045ms), nhưng lower(email)=x quét cả bảng (54.857ms); age+1=31 chậm 12ms còn age=30 chỉ 1ms; và một bất ngờ — LIKE 'x%' với index thường vẫn Seq Scan, phải dùng text_pattern_ops.