Bài viết mới nhất

Tổng 2300 bài
Lập trình 22/09/2026 5 phút

Timeout và context: đặt hạn cho mọi thao tác, và cái bẫy rò rỉ goroutine

Không đặt hạn thì một thao tác treo giữ luồng mãi, tài nguyên cạn dần. Bài này chạy thật trong Go: context timeout 200ms khiến thao tác 2 giây trả về sau 209ms với DeadlineExceeded; và đo cái bẫy quan trọng — 100 goroutine không nghe ctx.Done() vẫn rò rỉ dù đã cancel, còn 100 goroutine có nghe thì thoát sạch. Timeout chỉ có tác dụng nếu hàm thực sự tôn trọng context.

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

Backpressure: vì sao hàng đợi 'không giới hạn' là quả bom RAM chờ nổ

Khi bên sản xuất nhanh hơn bên tiêu thụ và hàng đợi không giới hạn, công việc dồn đống tới khi hết RAM. Bài này chạy thật trong Go: hàng đợi không giới hạn phình lên gần 4GB trong nửa giây, còn hàng đợi có giới hạn (bounded channel cap 100) chặn nguồn lại — producer tự chậm khớp consumer, RAM ổn định. Giải thích backpressure và khi nào chặn, khi nào từ chối.

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

Load shedding: thà từ chối 38% để 62% được phục vụ nhanh, còn hơn tất cả cùng chậm

Khi tải vượt capacity, nhận hết vào hàng đợi khiến MỌI request chậm — p99 nổ. Load shedding từ chối bớt sớm (503) để phần được nhận vẫn nhanh. Bài này chạy thật trong Go: không shedding thì 2000 request có p99 = 4,8 giây (ai cũng khổ); có shedding thì 62% được phục vụ ở p99 = 21ms, 38% nhận 503 ngay. Giải thích khác biệt với backpressure và cách ưu tiên request quan trọng.

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

Worker pool: vì sao 'một goroutine mỗi task' hỏng ở quy mô, và bao nhiêu worker là đủ

Tạo một goroutine cho mỗi task nghe tiện, nhưng với hàng triệu task nó bùng nổ thành hàng triệu goroutine tốn RAM và đè downstream. Bài này chạy thật trong Go: worker pool giữ đúng 11 goroutine cho 200.000 task (so với 200.001), và đo throughput theo số worker — với CPU-bound, throughput bão hòa quanh số core (10), thêm worker không nhanh hơn. Giải thích cách chọn N cho CPU-bound vs I/O-bound.

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

Cache stampede: khi cache hết hạn, 1000 request cùng đấm xuống DB — và singleflight gộp về 1

Cache là lá chắn cho database, nhưng đúng khoảnh khắc một key nóng hết hạn, hàng nghìn request cùng miss và cùng lao xuống nguồn — đó là cache stampede, thứ có thể quật sập DB ngay cả khi mọi thứ 'đang chạy tốt'. Bài này đo thật trong Go: 1000 goroutine cùng miss 1 key gọi nguồn 1000 lần; thêm singleflight, con số về đúng 1; và một cache LRU với truy cập lệch đạt hit rate 32.2%.

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

Idempotency: retry đã cứu bạn ở phần 3, giờ đừng để nó trừ tiền khách hai lần

Retry là lá chắn chống lỗi tạm thời, nhưng nó có một mặt tối: nếu request đầu tiên đã thành công mà phản hồi bị mất, lần retry sẽ chạy lại side-effect — khách bị trừ tiền hai lần. Bài này đo thật trong Go: một handler thanh toán không có idempotency bị retry 5 lần trừ tiền 5 lần (số dư 1000 → 500); thêm idempotency key, con số về đúng 1 lần; và 1000 goroutine gửi cùng key đồng thời vẫn chỉ trừ đúng 1 lần, kiểm bằng go run -race.