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ông cụ 22/09/2026 5 phút

git gc, fsck và bảo trì kho: dọn rác, nén, và vì sao reflog cứu object khỏi bị xóa

Thư mục .git tự phình rồi tự dọn. Bài cuối sê-ri Git đo thật: gc gom loose object thành packfile nén (9 object 36 KiB xuống 1.86 KiB), fsck báo object mồ côi, và điểm nhiều người hiểu sai — gc --prune=now KHÔNG xóa object mà reflog còn giữ; phải hết hạn reflog rồi gc mới xóa thật. Đây chính là lưới an toàn cứu commit tưởng đã mất.

Bảo mật 22/09/2026 6 phút

TOTP: mã 6 số của xác thực hai lớp thực ra là gì — tự tính bằng python

Mã 6 số đổi mỗi 30 giây trên Google Authenticator không hề được server gửi tới điện thoại. Nó là HMAC-SHA1 của bí mật chung với thời gian, cắt lấy 6 chữ số. Bài cuối sê-ri mật mã tự tính TOTP từ đầu bằng python theo RFC 6238: cùng bí mật + cùng mốc thời gian cho cùng mã, mã không đổi trong cửa sổ 30s rồi đổi sang cửa sổ mới.

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 Go 22/09/2026 9 phút

Middleware chain trong Go: xâu chuỗi xử lý HTTP bằng hàm bậc cao, gần như không tốn phí

Middleware trong Go là hàm func(http.Handler) http.Handler, xâu chuỗi được thành lớp xử lý HTTP kiểu củ hành. Đo thật trong Go 1.23: thứ tự thực thi vào-ra, middleware short-circuit dừng chuỗi, và một Chain combinator — 5 lớp middleware gần như không thêm chi phí vì chuỗi dựng một lần lúc khởi tạo.

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 Go 22/09/2026 11 phút

Integration test với testcontainers trong Go: dựng dịch vụ thật trong Docker

Mock chỉ giả lập hành vi bạn nghĩ dịch vụ có; bug thật nằm ở khác biệt với dịch vụ thật. testcontainers-go dựng database/Redis thật trong Docker ngay trong test rồi tự dọn. Đo thật: code testcontainers biên dịch sạch, và một integration test thật chống Redis (không mock) pass — kèm báo cáo trung thực về yêu cầu Docker socket.