OOM command not allowed when used memory > ‘maxmemory’

Tác giả Network Engineer, T.Ba 31, 2022, 11:08:03 CHIỀU

« Chủ đề trước - Chủ đề tiếp »

0 Thành viên và 1 Khách đang xem chủ đề.

OOM command not allowed when used memory > 'maxmemory'

Nếu đang sử dụng Redis, bạn có thể thấy nhật ký ứng dụng của mình bắt đầu hiển thị các thông báo lỗi sau:

Mã nguồn [Chọn]
$ tail -f error.log

OOM command not allowed when used memory > 'maxmemory'

Điều này có thể xảy ra mỗi khi thao tác WRITE được gửi đến Redis, để lưu trữ dữ liệu mới.

1. Nó có nghĩa là gì?

OOM command not allowed when used memory > 'maxmemory' có nghĩa là Redis đã được cấu hình với giới hạn bộ nhớ và đã đạt đến giới hạn cụ thể đó. Nói cách khác: bộ nhớ của nó đã đầy, nó không thể lưu trữ bất kỳ dữ liệu mới nào.

Bạn có thể xem các giá trị bộ nhớ bằng cách sử dụng công cụ dòng lệnh CLI của Redis.

Mã nguồn [Chọn]
$ redis-cli -p 6903

127.0.0.1:6903> info memory
# Memory
used_memory:3221293632
used_memory_human:3.00G
used_memory_rss:3244535808
used_memory_peak:3222595224

Nếu bạn chạy phiên bản Redis với mật khẩu trên đó, hãy thay đổi lệnh redis-cli thành lệnh sau đây:

Mã nguồn [Chọn]
$ redis-cli -p 6903 -a your_secret_pass
Lệnh info memory vẫn như cũ.

Ví dụ trên cho thấy một cá thể Redis được cấu hình để chạy với tối đa 3GB bộ nhớ và đã sử dụng tất cả.

2. Khắc phục sự cố lệnh OOM

Có 3 cách sửa lỗi tiềm năng.

2.1. Tăng bộ nhớ Redis

Có lẽ là dễ nhất để làm, nhưng nó có giới hạn của nó. Tìm cấu hình Redis, thường ở đâu đó trong thư mục /etc/redis/* và tăng giới hạn bộ nhớ.

Mã nguồn [Chọn]
$ vim /etc/redis/6903.conf

maxmemory 3gb

Ở đâu đó trong tập tin cấu hình đó, bạn sẽ tìm thấy tham số maxmemory. Sửa đổi nó theo nhu cầu của bạn và khởi động lại phiên bản Redis sau đó.

2.2. Thay đổi cài đặt vô hiệu bộ nhớ cache

Redis đang gặp lỗi vì nó không thể lưu trữ các mục mới trong bộ nhớ. Theo mặc định, cài đặt "cache invalidation" được đặt khá thận trọng, thành volatile-lru. Điều này có nghĩa là nó sẽ xóa một khóa có bộ hết hạn sử dụng thuật toán LRU.

Điều này có thể khiến các mục được giữ trong hàng đợi ngay cả khi các mục mới cố gắng được lưu trữ. Nói cách khác, nếu phiên bản Redis của bạn đã đầy, nó sẽ không chỉ vứt bỏ những mục cũ nhất (như Memcached sẽ làm).

Bạn có thể thay đổi điều này thành một số lựa chọn thay thế:

  • # portable-lru -> xóa khóa có bộ hết hạn sử dụng thuật toán LRU
  • # allkeys-lru -> xóa bất kỳ khóa nào phù hợp với thuật toán LRU
  • # variable-random -> xóa khóa ngẫu nhiên có bộ hết hạn
  • # allkeys-> random -> xóa khóa ngẫu nhiên, khóa bất kỳ
  • # bubble-ttl -> xóa khóa có thời gian hết hạn gần nhất (minor TTL)
  • # noeviction -> hoàn toàn không hết hạn, chỉ trả về lỗi khi ghi hoạt động

Trong cùng một cấu hình Redis, bạn có thể tìm thấy chỉ thị <code <maxmemory ở đâu đó trong thư mục /etc/redis/* cũng có một tùy chọn được gọi là maxmemory-policy.

Giá trị mặc định là:

Mã nguồn [Chọn]
$ grep maxmemory-policy /etc/redis/*

maxmemory-policy volatile-lru

Nếu bạn không thực sự quan tâm đến dữ liệu trong bộ nhớ, bạn có thể thay đổi nó thành một thứ gì đó nghiêm túc hơn, chẳng hạn như allkeys-lru.

Mã nguồn [Chọn]
$ vim /etc/redis/6903.conf

maxmemory-policy allkeys-lru

Sau đó, khởi động lại Redis của bạn một lần nữa.

Xin lưu ý rằng điều này có thể có nghĩa là Redis xóa các mục khỏi bộ nhớ của nó mà vẫn chưa được lưu vào đĩa. Điều này được cấu hình với tham số save, vì vậy hãy đảm bảo rằng bạn cũng xem xét các giá trị này để xác định chính sách "max memory" chính xác. Đây là các giá trị mặc định:

Trong ví dụ dưới đây, hành vi sẽ là lưu:

Mã nguồn [Chọn]
# sau 900 giây (15 phút) nếu ít nhất 1 khóa được thay đổi
# sau 300 giây (5 phút) nếu ít nhất 10 khóa được thay đổi
# sau 60 giây nếu ít nhất 10000 khóa được thay đổi
#
# Lưu ý: bạn có thể tắt tính năng lưu ở tất cả các bình luận trên tất cả các dòng lưu.

save 900 1
save 300 10
save 60 10000

Với lưu ý ở trên, việc đặt một giá trị khác maxmemory-policy có nghĩa là mất dữ liệu trong phiên bản Redis của bạn.

2.3. Lưu trữ ít dữ liệu hơn trong Redis

Mình biết đây là giải pháp ngu ngốc, phải không? Nhưng hãy tự hỏi bản thân: mọi thứ bạn đang lưu trữ trong Redis có thực sự cần thiết không? Hay bạn đang sử dụng Redis như một giải pháp bộ nhớ đệm và chỉ lưu trữ quá nhiều dữ liệu trong đó?

Nếu các truy vấn SQL của bạn trả về 10 cột nhưng thực tế bạn chỉ cần 3 trong số đó thường xuyên, chỉ cần lưu trữ 3 giá trị đó mà không phải tất cả 10.