Backend 01/09/2026 8 phút

Giết máy chính Redis giữa 2,7 triệu lệnh ghi: mất 0 — nhưng để bản sao chậm lại một chút rồi mới giết: mất 79%; 'bất đồng bộ' không có nghĩa 'mất một ít'

Sao chép của Redis là bất đồng bộ, và mọi tài liệu đều cảnh báo điều đó nghĩa là mất dữ liệu. Đo thật: liên kết khoẻ thì giết máy chính giữa 2,78 triệu lệnh vẫn mất đúng 0; nhưng cho bản sao chậm lại trước khi giết thì mất 79.592 trên 100.719 lệnh — gần bốn phần năm. Lượng mất không phải 'vài lệnh cuối', nó bằng ĐÚNG khoảng cách bản sao đang chậm ngay lúc đó. WAIT thu hẹp khoảng đó nhưng chậm 25 lần.

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

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

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.

Backend 01/09/2026 8 phút

Một lệnh lỗi giữa giao dịch Redis không huỷ gì cả — các lệnh khác vẫn chạy và vẫn giữ kết quả; 'transaction' của Redis không có chữ Rollback

Redis có MULTI/EXEC và gọi nó là giao dịch, nhưng nó bảo đảm ít hơn bạn tưởng. Đo thật: lỗi cú pháp lúc xếp hàng huỷ cả khối (EXECABORT), nhưng lỗi lúc chạy — INCR trên một chuỗi — chỉ báo lỗi đúng lệnh đó còn SET x và SET y vẫn chạy và vẫn giữ kết quả. Không có quay lui. Cái mạnh thật sự là WATCH — khoá lạc quan kiểu kiểm-rồi-đặt — và MULTI bọc quanh một đường ống gần như miễn phí (chênh 0,2%).

Backend 01/09/2026 8 phút

Một lệnh KEYS đẩy độ trễ PING của Redis từ 1 ms vọt lên 263 ms — trong khoảnh khắc đó khoảng 13.000 yêu cầu xếp hàng chờ, và DEL còn tệ hơn KEYS

Redis xử lý lệnh bằng một luồng duy nhất, nên một lệnh chậm không chỉ chậm — nó chặn đầu hàng của mọi khách khác. Đo thật trên 2 triệu khoá: KEYS '*' đẩy PING max lên 263,8 ms, SCAN chậm hơn 58% nhưng độ trễ tệ nhất ít hơn 63 lần vì nó nhường luồng; DEL một Hash 194 MB chặn 467,7 ms còn UNLINK chỉ 3,6 ms. Và độ trễ trung bình gần như không đổi — nên nếu chỉ đo trung bình, cả vấn đề này vô hình.