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.

2300 bài viết · Website
Backend 01/09/2026 8 phút

Đọc giá trị 10 MB từ Redis chỉ chậm hơn 1 KB đúng 3,5 mili giây — nhưng 20 khách đọc chậm cùng lúc thổi 10 MB dữ liệu thành 200 MB bộ nhớ mà maxmemory không hề hay biết

'Đừng lưu giá trị lớn trong Redis' là lời khuyên phổ biến, nhưng vấn đề thật không phải chỗ người ta nghĩ. Đo thật: đọc 10 MB gần như không chặn khách khác (Redis gửi theo đoạn), độ trễ dưới 10 KB phẳng hoàn toàn. Cái nguy hiểm là bộ đệm đầu ra — 20 khách đọc chậm biến 10 MB dữ liệu thành 215 MB used_memory, gấp 5.183 lần, và đó là cách một Redis 'chỉ chứa 5 GB' bị giết khi có 20 GB RAM.

Backend 01/09/2026 9 phút

Công thức khoá phân tán 'SET NX PX' được chép nhiều nhất Internet — và 50 trên 50 lần nó âm thầm mất khoá giữa chừng, để ba tiến trình cùng ghi vào một chỗ mà không ai biết

SET key value NX PX 30000 là công thức khoá phân tán ai cũng chép. Đo thật xem nó bảo đảm gì và ngừng bảo đảm ở đâu: khi công việc ngắn hơn TTL, nó chặn sạch 599 lần đua về 0; nhưng khi công việc dài hơn TTL, 50/50 lần lấy khoá đều mất khoá trước khi xong, ba tiến trình cùng vào vùng cấm mà không lỗi nào hiện ra. Redlock không cứu được — vấn đề nằm ở đồng hồ, không ở số lượng Redis.

Backend 01/09/2026 8 phút

Mở kết nối Redis mới cho mỗi lệnh chậm gấp 5,5 lần — và khi chạm trần 10.000 kết nối, chính redis-cli của bạn cũng không vào nổi để xem chuyện gì đang xảy ra

Bể kết nối là thứ mọi thư viện đều có và ít ai chỉnh. Đo thật: tái dùng kết nối nhanh gấp 5,5 lần mở mới mỗi lệnh (6,4 lần khi có mật khẩu), mật khẩu không làm Redis chậm mà chỉ làm việc MỞ kết nối chậm; mỗi kết nối chỉ tốn 1.928 byte và gần như 0 CPU khi ngồi không — nhưng có một trần cứng 10.000, và lúc chạm nó bạn mất luôn đường nhìn vào bên trong.

Backend 01/09/2026 8 phút

Ghi đè 7 triệu khoá trong lúc Redis đang chụp ảnh bộ nhớ làm chi phí copy-on-write nhảy từ 1,4 MB lên 87 MB — và INFO memory không hề thấy một byte nào trong đó

RDB chụp toàn bộ bộ nhớ Redis ra một tệp. Đo thật: BGSAVE 2 triệu khoá xong trong 1,21 giây, tệp nén 7,2 lần nhỏ hơn bộ nhớ, khách gần như không thấy độ trễ nhờ fork. Nhưng chi phí thật nằm ở copy-on-write: không ghi gì thì tốn 1,4 MB, ghi đè 7 triệu khoá lúc đang chụp thì tốn 87 MB — gấp 64 lần — và used_memory_rss của Redis đứng im vì các trang bị sao chép thuộc về tiến trình con. Đây là nguồn gốc lời khuyên 'chỉ dùng 50% RAM cho Redis'.

Backend 01/09/2026 8 phút

Giết Redis bằng SIGKILL với appendfsync=no — mất đúng 0 bản ghi, lặp ba lần vẫn vậy; vì tiến trình chết không phải mất điện, và người ta hay nhầm hai thứ đó

AOF ghi từng lệnh vào tệp thay vì chụp ảnh định kỳ, với ba chế độ appendfsync ai cũng gọi là nhanh/cân bằng/an toàn. Đo cả tốc độ lẫn lượng mất thật: no và everysec nhanh ngang nhau, always chậm 12,5 lần khi gọi từng lệnh nhưng chỉ 4,8 lần khi có đường ống. Bất ngờ lớn nhất: SIGKILL Redis với appendfsync=no vẫn mất 0 — vì write() đã vào bộ đệm kernel, và giết tiến trình không xoá được nó. appendfsync chỉ quyết định chuyện gì xảy ra khi mất điện.

Backend 01/09/2026 8 phút

Khởi động lại Redis: script Lua biến mất sạch, còn Function vẫn nguyên vẹn và chạy được ngay — nhưng tốc độ hai bên giống hệt nhau, vì cùng một máy Lua

Redis 7 thêm Functions, và câu hỏi đầu tiên ai cũng hỏi là 'khác gì Lua script'. Đo cả hai trên cùng logic: sau khi khởi động lại, EVALSHA trả NOSCRIPT còn FCALL chạy bình thường — vì function nằm trong chính dữ liệu, đi theo RDB/AOF/bản sao, còn script chỉ nằm trong bộ nhớ tạm. Nhưng FCALL 20.520 ops/s so EVALSHA 20.256, chênh trong nhiễu: đừng chuyển vì hiệu năng, chuyển vì vận hành — cờ no-writes được thi hành thật, tên có nghĩa thay mã băm, và mã đi theo quy trình triển khai.