Q

Quản trị viên

Là một lập trình viên yêu công nghệ, thích viết blog để chia sẻ kiến thức, kinh nghiệm lập trình và những điều thú vị trong thế giới tech.

2312 bài viết · Website
Cơ sở dữ liệu 22/09/2026 5 phút

Khóa ngoại có cần index không trong PostgreSQL: có, và nó không tự tạo

PostgreSQL tự tạo index cho PRIMARY KEY và UNIQUE nhưng KHÔNG cho cột khóa ngoại. Đo thật: thiếu index đó, xóa một dòng cha phải quét cả 5 triệu dòng con (179 ms so với 0,7 ms), và JOIN cha con seq scan 52 ms so với 0,17 ms. Vì sao, và khi nào vẫn bỏ được. PostgreSQL 16.

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

Rate limiting với Redis: fixed window, sliding window và token bucket — ba thuật toán, ba mức mượt

Giới hạn số request để chống lạm dụng là bài toán backend kinh điển, và Redis là công cụ lý tưởng nhờ các thao tác nguyên tử. Bài này đo thật trong redis-lab ba thuật toán: fixed window (INCR+EXPIRE, đơn giản nhưng burst ở ranh giới), sliding window (sorted set theo timestamp, mượt hơn, không burst), và token bucket (cho phép burst có kiểm soát). Với limit 5, cả hai đều cho 5 request qua và chặn request 6-7 — nhưng khác nhau ở độ chính xác quanh ranh giới cửa sổ.

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

Sharding: đo thật trên 5 PostgreSQL — chia theo khoảng với khoá Zipf lệch 3,75 lần, hash cũng lệch 1,54 vì một user không chia nhỏ được, thêm mảnh bằng mod N dời 80% khoá, và đọc trong lúc dời trượt 48% nếu không đọc kép

Năm container PostgreSQL 16 làm năm mảnh, 200.000 sự kiện của 100.000 user. Chia theo khoảng user_id đẹp với khoá đều (lệch 1,00) nhưng với khoá Zipf thì mảnh đầu ôm 187.329 dòng, lệch 3,75; hash cũng lệch 1,54 vì user #0 một mình chiếm 13,5% dữ liệu. Muối top-10 user nóng hạ xuống 1,25, đổi lại đọc user nóng phải hỏi 4 mảnh. Chia theo thời gian dồn mọi dòng mới vào một mảnh: ghi chậm 1,6 lần. Thêm mảnh thứ 5: mod N dời 79,9% khoá, jump hash dời 20,0%; dời thật 39.684 dòng mất 251 ms, bộ đọc chỉ hỏi vị trí mới trượt 47,8%, đọc kép mới rồi cũ trượt 0.

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

Service discovery trong Go: đăng ký, health check TTL và round-robin

Địa chỉ cứng không co giãn: dịch vụ scale, chết, đổi IP thì client không biết. Service discovery giải bằng sổ đăng ký động — dịch vụ tự đăng ký và heartbeat, client tra để tìm bản sống. Bài dựng registry trong Go và đo thật: round-robin phân đều 3/3/3, health check loại bản chết, traffic tự né.

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

String internals trong Go: header 16 byte, bất biến, và chi phí ẩn của []byte(s)

String là header 16 byte trỏ vào dữ liệu bất biến, không có cap. Đo thật: substring s[7:13] miễn phí (chia sẻ backing, 0 cấp phát) nhưng chuyển string sang []byte phải copy toàn bộ (21 ns, 1 cấp phát) vì string bất biến còn byte sửa được. Vì sao và khi nào tốn kém. Go 1.23.