Sửa lỗi Redis OOM: 'Command not allowed when used memory > maxmemory'

intermediate🔴 Redis2026-07-25| Redis (v4.0 đến v7.2+), Linux (Ubuntu, Debian, CentOS), Docker, Managed Redis (AWS ElastiCache, Azure Cache)

Error Message

(error) OOM command not allowed when used memory > 'maxmemory'
#redis#devops#quan-tri-database#linux-server#toi-uu-hieu-suat

TL;DR: Cách khắc phục nhanh trong 30 giây

Instance Redis của bạn đã chạm ngưỡng giới hạn bộ nhớ và hiện đang từ chối mọi thao tác ghi để tự bảo vệ. Bạn có thể khôi phục dịch vụ ngay lập tức bằng cách tăng giới hạn hoặc thay đổi cách Redis xử lý khi đầy bộ nhớ. Chạy các lệnh sau trong redis-cli:

# 1. Kiểm tra lượng bộ nhớ thực tế đang sử dụng
INFO memory

# 2. Tăng giới hạn lên 4GB (ví dụ: sử dụng 80% RAM khả dụng của hệ thống)
CONFIG SET maxmemory 4gb

# 3. Kích hoạt tính năng tự động xóa dữ liệu cũ để giải phóng không gian
CONFIG SET maxmemory-policy allkeys-lru

Giải pháp này có hiệu lực ngay lập tức mà không cần khởi động lại. Để ngăn lỗi tái diễn sau khi khởi động lại máy chủ, hãy nhớ cập nhật tệp redis.conf với các giá trị tương tự.

Tại sao lỗi này xảy ra?

Redis là một cơ sở dữ liệu lưu trữ trên bộ nhớ (in-memory). Không giống như PostgreSQL hay MySQL (có thể ghi tràn ra đĩa cứng), Redis tuân thủ nghiêm ngặt giới hạn maxmemory được định nghĩa trong cấu hình. Khi bạn thấy lỗi này, nghĩa là bạn đã chạm ngưỡng giới hạn đó.

Theo mặc định, nhiều bản cài đặt Redis sử dụng chính sách noeviction. Điều này có nghĩa là khi RAM đầy, Redis sẽ từ chối chấp nhận dữ liệu mới thay vì xóa các key cũ. Trong khi các lệnh đọc (như GET hoặc EXISTS) vẫn hoạt động bình thường, các lệnh ghi (SET, HSET, LPUSH) sẽ thất bại với lỗi OOM.

Hãy chú ý đến chỉ số mem_fragmentation_ratio. Nếu con số này trên 1.5, Redis có thể đang giữ một lượng bộ nhớ mà nó không thực sự dùng để lưu dữ liệu, khiến hệ thống có cảm giác bị "đầy" sớm hơn dự kiến.

Các cách khắc phục hiệu quả

1. Nới rộng giới hạn bộ nhớ

Nếu máy chủ của bạn còn dư RAM, cách dễ nhất là cấp thêm không gian cho Redis. Nếu bạn đang chạy trên một VPS 16GB và Redis bị giới hạn ở mức 2GB, bạn vẫn còn rất nhiều tài nguyên dư thừa.

redis-cli
> CONFIG GET maxmemory
> CONFIG SET maxmemory 8gb

Lưu ý quan trọng: Tránh thiết lập maxmemory 0 (không giới hạn) trên các máy chủ production. Nếu Redis tiêu thụ toàn bộ RAM vật lý, cơ chế OOM Killer của Linux có khả năng sẽ can thiệp và dừng tiến trình Redis đột ngột, dẫn đến việc hệ thống bị ngừng hoạt động hoàn toàn.

2. Tự động dọn dẹp dữ liệu (Eviction)

Trong hầu hết các kịch bản bộ nhớ đệm (caching), bạn không cần giữ lại mọi key mãi mãi. Bạn có thể yêu cầu Redis hoạt động như một bộ đệm thông minh bằng cách xóa dữ liệu cũ hoặc ít sử dụng khi chạm giới hạn.

Cập nhật tệp redis.conf hoặc sử dụng CONFIG SET để chọn một chính sách:

  • allkeys-lru: Xóa các key ít được sử dụng gần đây nhất. Đây là lựa chọn tiêu chuẩn cho hầu hết các ứng dụng web.
  • volatile-ttl: Chỉ xóa các key có thiết lập thời gian hết hạn (TTL), ưu tiên những key sắp hết hạn.
  • allkeys-lfu: Xóa các key ít được truy cập thường xuyên nhất (hữu ích nếu một số dữ liệu được truy cập nhiều gấp 1000 lần so với phần còn lại).

3. Sửa lỗi lưu dữ liệu nền (Overcommit Memory)

Đôi khi bạn có đủ RAM, nhưng Redis vẫn báo lỗi OOM trong quá trình thực hiện BGSAVE (chụp snapshot dữ liệu xuống đĩa). Điều này xảy ra do Linux quá thận trọng trong việc phân bổ bộ nhớ khi Redis cố gắng tạo tiến trình con (fork child process).

Để khắc phục, hãy cho phép kernel "overcommit" bộ nhớ bằng cách chạy lệnh sau với quyền root:

sysctl vm.overcommit_memory=1

Thêm vm.overcommit_memory = 1 vào /etc/sysctl.conf để duy trì thiết lập này sau khi khởi động lại. Điều này đảm bảo Redis có thể lưu dữ liệu xuống đĩa ngay cả khi mức sử dụng bộ nhớ đang cao.

4. Truy tìm các "Big Key"

Một hash hoặc list khổng lồ thường là thủ phạm. Một key duy nhất chứa blob JSON 500MB là một "quả bom nổ chậm" đối với việc quản lý bộ nhớ. Sử dụng trình quét tích hợp để tìm chúng:

# Lệnh này quét toàn bộ keyspace mà không làm treo máy chủ
redis-cli --bigkeys

Nếu bạn tìm thấy một danh sách có 1.000.000 phần tử mà bạn chỉ cần dùng trong 24 giờ, hãy áp dụng TTL: EXPIRE my_massive_list 86400.

Xác nhận kết quả

Đừng chỉ rời đi khi lỗi biến mất. Hãy kiểm tra tình trạng sức khỏe của instance bằng các bước sau:

  • Kiểm tra khoảng cách: Chạy INFO memory và so sánh used_memory_human với maxmemory_human. Bạn nên để lại một khoảng đệm an toàn.
  • Xác minh khả năng ghi: Chạy SET health_check 1. Nếu kết quả trả về OK, ứng dụng của bạn đã hoạt động bình thường trở lại.
  • Theo dõi việc thu hồi (eviction): Nếu bạn đã bật chính sách thu hồi, hãy chạy redis-cli info stats | grep evicted_keys. Nếu con số này tăng lên, Redis đang giải phóng không gian thành công cho dữ liệu mới.

Related Error Notes