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

Bộ nhớ và big key trong Redis: một key 34 MB có thể làm nghẽn cả server, và vì sao đừng bao giờ KEYS *

Redis chạy một luồng — nên một lệnh O(n) trên key khổng lồ chặn mọi client khác. Bài này đo thật trong redis-lab: một hash 500.000 field chiếm 34,5 MB; HGETALL trên nó mất 224ms (so với 1ms cho hash nhỏ) và suốt thời gian đó cả server khựng; và KEYS * quét toàn bộ keyspace O(n) chặn server, trong khi SCAN duyệt từng lô không block. Hiểu để một key hay một lệnh không kéo sập Redis.

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

cgroups v2 giới hạn bộ nhớ đo thật: --memory=128m đặt memory.max 128 MiB, vượt trần là OOM killer giết chứ không chạy chậm, container chết với exit 137 và OOMKilled=true, nhưng OOM chỉ giết tiến trình ngốn RAM nên PID 1 sống thì container sống

Khác CPU bị ghìm, bộ nhớ vượt trần thì OOM killer giết tiến trình. --memory=128m đặt memory.max 134217728 byte. Tắt swap rồi cho một tiến trình ngốn 10 MB mỗi vòng: memory.current leo 95, 105, 115, 125 MB rồi vượt 128 MB là bị SIGKILL, container exit 137 và OOMKilled=true. memory.events đếm max là số lần chạm trần và oom_kill là số tiến trình bị giết. Điểm quan trọng: OOM giết tiến trình ngốn RAM, không nhất thiết cả container, nên nếu PID 1 không phải kẻ ngốn thì container vẫn Running. memory.high ghìm mềm thì Docker không phơi ra.

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

Bộ nhớ trong cgroup đo thật: không phải byte nào cũng như nhau trước OOM killer, đọc 1200 MB page cache trong cgroup 128 MB vẫn sống vì cache thu hồi được, còn cấp phát RSS ẩn danh vượt trần thì OOM killer SIGKILL, và memory.pressure cảnh báo sớm

memory.current của một cgroup gồm hai loại byte rất khác nhau: anon (RSS, không thu hồi được) và file (page cache, thu hồi được). Đo bằng /sys/fs/cgroup trong cgroup 128 MB: đọc file 400 MB ba lượt là 1200 MB, gấp chín lần giới hạn, vẫn không OOM vì kernel đẩy page cache ra, memory.current giữ ở 120 MB, file cache 114 MB, oom_kill 0, memory.pressure some tăng 15505 µs. Cấp phát RSS bằng bytearray chạm từng trang thì OOM killer SIGKILL ở đúng trần, oom_kill 0 lên 1. Đặt --memory theo đỉnh RSS, không theo memory.current.

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

Dữ liệu lớn hơn RAM đo thật: DuckDB tràn trung gian ra đĩa thay vì sập, nên sort 40 triệu dòng dưới giới hạn 600 MB vẫn xong sau khi ghi 976 MB ra đĩa (chậm hơn 2,7 lần so với chạy gọn trong RAM), còn SUM streaming chạy với bộ nhớ chỉ 150 MB

DuckDB xử lý được tập dữ liệu lớn hơn bộ nhớ nhờ tràn (spill) trạng thái trung gian ra đĩa thay vì sập OOM. Đo thật trên 40 triệu dòng (~762 MB bung ra): sort toàn bộ dưới giới hạn cứng 600 MB vẫn hoàn thành sau khi ghi 976 MB ra đĩa, mất 3358 ms so với 1246 ms khi cho 8 GB chạy gọn trong RAM, chậm hơn 2,7 lần. Toán tử streaming như SUM chỉ giữ một bộ tích luỹ nên chạy với bộ nhớ hằng số, SUM 40 triệu dòng với giới hạn 150 MB mất 151 ms không spill. Blocking (sort, agg, join) thì spill, streaming thì không.