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

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

PgBouncer đo thật: 1.000 client chạy trên đúng 20 backend PostgreSQL trong khi 300 client trực tiếp bị từ chối, proxy một luồng chạm trần 70.000 TPS so với 235.000 trực tiếp, và một SET work_mem của một client làm bẩn pool cho 50 client sau

PgBouncer 1.26 ở transaction mode với pool 20 trước PostgreSQL 16 max_connections 100. Connect mỗi giao dịch: 1.224 TPS trực tiếp, 2.322 qua pool. 300 client trực tiếp nhận FATAL too many clients; 1.000 client qua pool chạy trên 20 backend với 951 client xếp hàng, 64.088 TPS. Nhưng PgBouncer một luồng chạm trần 70.000 TPS truy vấn đơn giản so với 235.000 trực tiếp. Một client SET work_mem rồi ngắt: 50 trong 50 client mới nhận 64MB vì transaction mode không reset phiên. Prepared statement lỗi với max_prepared_statements 0, chạy 89.480 TPS khi bật 100. Pool cạn: SELECT 1 chờ 2,9 giây.

Web 22/09/2026 6 phút

HTTP/1.1 vs HTTP/2: multiplexing nhiều luồng trên một kết nối — đo thật

HTTP/1.1 gửi request tuần tự trên mỗi kết nối, nên response chậm chặn hết phần sau (head-of-line blocking) — trình duyệt phải mở tới 6 kết nối để lách. HTTP/2 chia message thành frame nhị phân, đan xen nhiều luồng trên một kết nối. Bài này đo thật bằng nginx và curl: thương lượng giao thức, log server xác nhận, và multiplexing nhanh hơn khi tải nhiều tài nguyên.

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

Pub/Sub và Streams trong Redis: hai cách nhắn tin dễ nhầm, khác nhau căn bản ở chỗ giữ hay vứt message

Redis có hai cơ chế nhắn tin trông giống nhau nhưng khác nhau một trời một vực. Pub/Sub là loa phát thanh — ai đang nghe thì nghe, phát trước khi ai subscribe là mất luôn. Streams là sổ ghi bền — lưu lại, đọc lại, phát lại, có consumer group chia việc như Kafka thu nhỏ. Bài này đo thật trong redis-lab: PUBLISH khi không subscriber trả về 0 (mất), XADD rồi XRANGE đọc lại được, và consumer group chia entry cho c1/c2 với XACK theo dõi.

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

Giao dịch phân tán: đo thật 2PC bằng PREPARE TRANSACTION trên hai PostgreSQL — đắt gấp 1,5 lần, điều phối chết giữa chừng là khoá bị giữ vô thời hạn, và saga rẻ hơn nhưng người ngoài thấy trạng thái dở 34,6% thời gian

Trừ ví ở PostgreSQL này, tạo đơn ở PostgreSQL kia. Hai commit rời: bước hai hỏng là tiền mất không dấu vết, 100/100 lần. 2PC bằng PREPARE TRANSACTION rồi COMMIT PREPARED: đúng 100/100, giá 0,45 so với 0,30 ms vì thêm hai lượt mạng và fsync cho bản ghi prepare; điều phối viên chết giữa hai pha thì hai giao dịch treo trong pg_prepared_xacts, sống qua restart, giữ khoá dòng vô thời hạn. Saga với bước bù: đúng 100/100, rẻ nhất 0,20 ms, nhưng người đọc ngoài thấy ví và đơn không khớp 34,6% thời gian; 2PC cũng lộ 11,5% vì hai COMMIT PREPARED không đồng thời.

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

WAL và checkpoint đo thật: một dòng UPDATE ngay sau checkpoint tốn 6.160 byte nhật ký, lần hai 120 byte; full_page_writes chiếm 84% WAL của pgbench; max_wal_size 64 MB gây 66 checkpoint trong 40 giây, TPS giảm 39% và WAL gấp đôi

Đo WAL bằng pg_current_wal_lsn trước và sau từng lệnh trên PostgreSQL 16: insert 160 byte mỗi dòng, có index 226, update ngay sau checkpoint 381 so với 243 lần hai, đổi khoá index 453. Ở mức một dòng: update đầu tiên sau checkpoint ghi 6.160 byte vì chụp cả trang 8 KB, update thứ hai cùng trang 120 byte. pgbench 10 giây sinh 390 MB WAL với full_page_writes bật và 62 MB khi tắt. Bốn cấu hình checkpoint dưới cùng tải 40 giây: mặc định 10.632 TPS với 2 checkpoint; max_wal_size 64 MB gây 66 checkpoint, 6.483 TPS và 2.133 MB WAL; completion target 0.1 giữ TPS trung bình nhưng có giây tụt còn 2.966.