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

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

Test double đo thật: cùng một dịch vụ, viết test bằng stub, mock và fake rồi refactor 5 lần và cấy 4 lỗi — stub không bao giờ vỡ nhưng lọt 3/4 lỗi, mock bắt đủ 4 lỗi nhưng vỡ ở cả 4 refactor giữ nguyên hành vi, fake bắt đủ 4 và vỡ 0

Một Service.Place với hai phụ thuộc Repo và Mailer, ba bộ test cùng bốn ca nhưng ba kiểu thay thế: stub trả giá trị đóng sẵn, mock ghi lại và khẳng định chuỗi lời gọi, fake là cài đặt thu nhỏ trong bộ nhớ. Tạo 5 refactor giữ nguyên hành vi bên ngoài và 4 lỗi thật, chạy cả ba bộ trên từng bản. Stub: 0 test vỡ khi refactor nhưng chỉ bắt 1/4 lỗi, lọt quên gửi thư, lưu đơn hai lần, gửi thư khi lưu hỏng. Mock: bắt 4/4 lỗi nhưng 6 test phải sửa qua 4 refactor, kể cả khi chỉ bỏ một lần gọi thừa. Fake: bắt 4/4, vỡ 0. Thêm một phương thức vào interface làm cả ba bộ lỗi biên dịch.

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

Sao lưu PostgreSQL đo thật: pg_dump và pg_basebackup trên cùng 613 MB — dump nén 69 MB mất 2,9 giây, basebackup 651 MB mất 0,9 giây, tải đang chạy giảm 9% đến 15%, và dump chụp lúc bắt đầu còn basebackup nhất quán lúc kết thúc

Hai kiểu sao lưu khác bản chất, đo trên một cơ sở dữ liệu 613 MB với pgbench và một bảng một triệu dòng md5. Sáu biến thể: pg_dump SQL thuần 407 MB trong 0,89 giây, custom nén 69 MB trong 2,92 giây, thư mục song song 4 tiến trình 2,33 giây; pg_basebackup thư mục 651 MB trong 0,89 giây, tar gzip 100 MB trong 6,1 giây. Dưới tải pgbench 8 client, dump làm TPS giảm 9%, basebackup gzip giảm 15%, không khoá bảng nào. Chèn 1.000 dòng trong lúc sao lưu: dump giữ 1.000 dòng lúc bắt đầu, basebackup giữ 1.200 dòng lúc kết thúc chép, và container mới khởi động từ bản basebackup trong 758 ms.

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

Phân vùng mạng thật bằng iptables: cắt một nút etcd 20 giây — thiểu số từ chối ghi sau đúng 1,1 s nhưng vẫn trả lời đọc serializable cũ 20 giây, cô lập leader làm đa số mất 2 s, và lease biến mất ở đa số 0,71 s trước khi người giữ hay

Cụm etcd ba nút, cắt mạng thật bằng iptables trong network namespace của từng container, client Go đo cả ba nút mỗi 100 ms. Cô lập một follower: hai nút còn lại ghi 202/202, nút bị cắt ghi 1/21 và đọc tuyến tính 1/21 nhưng đọc serializable 21/21 với dữ liệu cũ dần tới 20 giây, không một lỗi nào. Cô lập leader: đa số mất 2 giây bầu lại, leader cũ không nhận một ghi nào. Tách rời cả ba: không ai ghi được sau 0,2 giây. Lease TTL 5 s giữ qua nút bị cắt: đa số thấy khoá mất ở +5,24 s, người giữ mới biết ở +5,95 s. Khi leader bị cô lập, leader mới gia hạn mọi lease nên khoá sống tới +9,33 s.

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

Bắt tay WebSocket đọc từng byte: 155 byte đi, 129 byte về, Sec-WebSocket-Accept tự tính bằng SHA-1 khớp đúng ví dụ của RFC, bắt tay mất 80 µs ngang một GET mở kết nối mới nhưng gấp 8 lần GET keep-alive, và bốn cách bắt tay hỏng kèm mã lỗi thật

Một client Go viết tay từng dòng header bắt tay WebSocket và in nguyên văn phản hồi: 155 byte đi, 129 byte về sau 333 µs, Accept là base64 của SHA-1 key nối GUID, khớp đúng ví dụ RFC 6455. Đo 2.000 lần: dial WebSocket mất 80 µs p50, GET mở kết nối mới 94 µs, GET keep-alive 10 µs. Sau bắt tay, một thông điệp 10 byte tốn 16 byte đi và 12 byte về so với 99 byte header tối thiểu của một GET. Bốn cách hỏng đo thật: thiếu Upgrade 400, version 12 cũng 400 thay vì 426, Origin lạ 403, proxy bỏ header Upgrade gây bad handshake trong khi ReverseProxy của Go cho 101.

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

TLS termination ở đâu, đo thật: với keep-alive TLS trong app tốn thêm 0 µs đo được, hop qua proxy tốn gấp 3,7 lần CPU và cộng 0,12 ms, mã hoá lại 64 KB qua sidecar chậm gấp 6,5 lần, còn khi mỗi request là một kết nối mới thì proxy gom hết bắt tay

Bốn topology cùng một app Go: plaintext, TLS trong app, proxy kết thúc TLS rồi plaintext vào app, và proxy mã hoá lại. Keep-alive 64 kết nối 256 byte: app plaintext 31 µs CPU mỗi request, app TLS 29 µs, qua proxy thêm 110 µs ở proxy và p50 từ 0,35 lên 1,83 ms. Body 64 KB: TLS trong app thêm 22 µs, mã hoá lại qua proxy tốn 143 cộng 300 µs và p50 7,79 ms. Kết nối mới mỗi request: TLS trong app 353 µs, qua proxy app còn 52 µs vì bắt tay dồn về proxy. Một kết nối tuần tự: hop loopback cộng 0,12 ms; netem 1 ms RTT cho hop nội bộ đẩy p50 từ 0,21 lên 1,65 ms. Kèm ALPN h2 so với h1.

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

Cây tìm kiếm nhị phân: O(log n) hay O(n) tùy cách bạn chèn — và vì sao map Go không dùng cây

Cây BST hứa tra cứu O(log n), nhưng chèn dữ liệu đã sắp vào nó một cách ngây thơ thì cây suy biến thành danh sách liên kết O(n). Bài này đo thật trong go-lab: cùng N=64.000, BST cân bằng tra cứu 99 ns còn BST suy biến 29.618 ns — chậm gấp 300 lần. Map Go (hash) còn nhanh hơn cả cây cân bằng. Vậy khi nào mới nên dùng cây?