Backend 01/09/2026 7 phút

Cùng 199 trường, cùng dữ liệu, nhưng một Hash tốn 16.256 byte còn cái kia 1.840 byte — chênh 8,8 lần chỉ vì một khoá từng phình to rồi co lại

Redis đổi cách mã hoá tập hợp khi nó vượt ngưỡng, nhưng KHÔNG BAO GIỜ đổi ngược. Đo thật: một Hash từng có 513 trường rồi xoá còn 199 vẫn tốn 16.256 byte, gấp 8,8 lần một Hash tạo mới đúng 199 trường (1.840 byte). Đây là rò rỉ bộ nhớ âm thầm nhất trong Redis — phình trong đợt cao điểm rồi giữ chi phí lúc lớn nhất vĩnh viễn. Và một giá trị vượt 64 byte đẩy cả Hash sang mã hoá đắt.

Backend 01/09/2026 8 phút

Đếm một triệu phần tử khác nhau bằng 14.384 byte với sai số 0,12% — và HyperLogLog còn ghi nhanh hơn Set 1,6 lần vì nó không lưu phần tử nào

Hai kiểu dữ liệu ít dùng nhất của Redis cũng là hai kiểu tiết kiệm nhất. Đo cả bộ nhớ lẫn sai số: HyperLogLog đếm một triệu phần tử khác nhau trong 14.384 byte cố định (nhỏ hơn Set 3.364 lần) với sai số dưới 0,5%, và PFADD nhanh hơn SADD vì nó băm rồi vứt, không cấp phát. Bitmap nhỏ hơn Set 35 lần nhưng có bẫy: bộ nhớ phụ thuộc chỉ số bit lớn nhất, không phụ thuộc số bit đã đặt.

Backend 01/09/2026 8 phút

Một tiêu thụ Redis Stream quên gọi XACK thổi 1,4 MB thành 28 MB — gấp 19,7 lần — và XTRIM cắt stream không cứu được một byte

List làm hàng đợi được và nhiều hệ thống dùng nó. Đo xem Stream cho thêm gì: nó gọn hơn List 24% dù mang thêm id, và khác biệt thật là khi tiến trình chết — bản tin ở lại danh sách chờ tới khi có ai XACK, còn List thì mất dấu. Nhưng danh sách chờ là cái bẫy: quên XACK làm bộ nhớ phình 19,7 lần, và XTRIM không cứu được vì chỗ tốn nằm ở pending, không ở stream. Giám sát XPENDING, không chỉ XLEN.

Backend 01/09/2026 7 phút

Một lệnh SET vô tình xoá sạch TTL và biến phiên đăng nhập 30 phút thành khoá sống mãi mãi — còn APPEND lại giữ nguyên hạn, dù cả hai đều sửa giá trị

Đặt TTL là thao tác phổ biến nhất trong Redis sau GET và SET. Đo ba thứ ít ai kiểm: Redis dọn 100.000 khoá hết hạn trong dưới một giây (nhanh hơn lời đồn), SET xoá TTL nhưng APPEND/INCRBY thì không — vì lệnh thay thế cả khoá thì mất hạn còn lệnh sửa tại chỗ thì giữ — và mỗi TTL tốn thêm 34,4 byte (+19%). Quên KEEPTTL là nguồn của một lớp lỗi khoá bất tử không lỗi, không cảnh báo.

Backend 01/09/2026 8 phút

Đặt volatile-lru khi không khoá nào có TTL chính là tắt hẳn việc dọn dẹp — Redis từ chối ghi trong khi 166.000 khoá bỏ được vẫn nằm nguyên trong RAM

Khi Redis chạm trần bộ nhớ, chính sách maxmemory quyết định nó dọn gì. Đo tám chính sách trên cùng một phép thử: volatile-lru với dữ liệu không TTL cho kết quả y hệt noeviction (0 khoá bị đuổi, 27.610 lỗi ghi) — cái bẫy dễ vấp nhất. Và LRU của Redis là gần đúng (lấy mẫu 5 khoá) nên chỉ giữ được 545/1000 khoá nóng, trong khi LFU giữ đủ 1.000/1.000 mà không cần chỉnh gì.

Backend 01/09/2026 8 phút

Xoá 270.000 khoá khỏi Redis mà RSS không giảm một byte — bộ nhớ trả về theo cả trang, không theo từng khoá, nên xoá rải rác để lại lỗ không thu hồi được

mem_fragmentation_ratio là chỉ số hay bị hiểu sai nhất trong INFO memory. Đo ở ba trạng thái: một instance gần rỗng có tỷ lệ 16,59 mà hoàn toàn khoẻ; xoá 90% khoá thì used_memory tụt còn RSS đứng im ở 107,6 MB vì jemalloc chỉ trả một trang về khi MỌI đối tượng trong đó đã chết. Và activedefrag y, tự nó, thường là lệnh không có tác dụng vì ngưỡng mặc định 100 MB. Cảnh báo trên allocator_frag_bytes, đừng trên tỷ lệ.