Sửa lỗi Redis 'fork: Cannot allocate memory' trên Linux

intermediate🔴 Redis2026-06-28| Redis chạy trên Linux (Ubuntu, Debian, CentOS, RHEL) trong các hoạt động BGSAVE hoặc BGREWRITEAOF.

Error Message

Can't save in background: fork: Cannot allocate memory
#bgsave#fork#overcommit-memory#persistence#aof#linux

Vấn đềNếu nhật ký (log) của Redis hiển thị lỗi Can't save in background: fork: Cannot allocate memory, có khả năng bạn đang gặp phải một rào cản quản lý bộ nhớ phổ biến trên Linux. Lỗi này thường xảy ra trong lệnh BGSAVE hoặc BGREWRITEAOF. Khi lỗi xuất hiện, Redis sẽ ngừng tạo bản sao lưu dữ liệu (snapshots). Đây là một rủi ro lớn. Nếu máy chủ gặp sự cố lúc này, bạn có thể mất toàn bộ các thao tác ghi dữ liệu kể từ lần lưu thành công cuối cùng.

Nguyên nhân gốc rễRedis xử lý việc lưu trữ dữ liệu bằng cách gọi fork() để tạo một tiến trình con. Tiến trình con này sử dụng cơ chế Copy-on-Write (COW) để chia sẻ bộ nhớ với tiến trình cha. Mặc dù cơ chế này hiệu quả, nhưng kernel Linux thường quá thận trọng. Theo mặc định, kernel sẽ ước tính liệu nó có đủ RAM để xử lý kịch bản xấu nhất khi tiến trình con cuối cùng cần lượng bộ nhớ bằng với tiến trình cha hay không.

Hãy tưởng tượng bạn có một máy chủ RAM 16GB. Nếu Redis đang sử dụng 9GB, kernel có thể từ chối lệnh fork() vì lo ngại tổng mức sử dụng có thể lên tới 18GB, vượt quá RAM vật lý của bạn. Nó chặn yêu cầu để ngăn chặn sự cố toàn hệ thống, ngay cả khi tiến trình con thực tế chỉ cần thêm vài trăm megabyte bộ nhớ.

Các bước khắc phục### Bước 1: Kiểm tra cài đặt Overcommit hiện tạiBắt đầu bằng cách kiểm tra cách máy chủ Linux của bạn đang xử lý việc overcommit bộ nhớ. Chạy lệnh sau:

cat /proc/sys/vm/overcommit_memory

Giá trị 0 nghĩa là kernel sử dụng phương pháp phỏng đoán (heuristic). Đây hầu như luôn là nguyên nhân khiến các instance Redis sử dụng hơn 50% bộ nhớ hệ thống hiện có gặp lỗi.

Bước 2: Kích hoạt Overcommit bộ nhớ ngay lập tứcBạn có thể khắc phục lỗi này ngay lập tức mà không cần khởi động lại máy chủ hay dịch vụ. Hãy đặt chế độ overcommit thành 1. Điều này yêu cầu kernel tin tưởng ứng dụng và luôn cho phép cấp phát bộ nhớ.

sudo sysctl vm.overcommit_memory=1

Sau khi áp dụng, hãy thử ép buộc lưu dữ liệu để xác minh kết quả:

redis-cli BGSAVE

Bước 3: Lưu cấu hình vĩnh viễnLệnh sysctl chỉ có tác dụng tạm thời và sẽ bị đặt lại sau khi khởi động lại. Để thay đổi này có hiệu lực vĩnh viễn, bạn phải cập nhật tệp cấu hình hệ thống.

  • Mở tệp cấu hình:sudo nano /etc/sysctl.conf- Thêm dòng này vào cuối tệp:vm.overcommit_memory = 1- Lưu và thoát (Ctrl+O, Enter, Ctrl+X).- Tải lại các cài đặt để đảm bảo chúng đã hoạt động:sudo sysctl -p### Bước 4: Đánh giá không gian SwapNếu lỗi vẫn tiếp diễn ngay cả khi đã đặt overcommit thành 1, hệ thống của bạn thực sự đã cạn kiệt tài nguyên. Kiểm tra mức sử dụng hiện tại bằng lệnh free -m. Nếu máy chủ 16GB của bạn chỉ còn trống 100MB và không có swap (0B), bạn cần thêm không gian để hệ thống "thở". Thêm một tệp swap 4GB có thể đóng vai trò như một lưới an toàn cho những đợt tăng đột biến ngắn trong quá trình fork.
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Xác minhXác nhận việc khắc phục bằng cách theo dõi log Redis trong thời gian thực khi bạn kích hoạt lưu dữ liệu. Mở hai cửa sổ terminal.

# Terminal 1: Theo dõi nhật ký
tail -f /var/log/redis/redis-server.log

# Terminal 2: Kích hoạt lưu dữ liệu
redis-cli BGSAVE

Nếu khắc phục thành công, các dòng nhật ký sẽ cho biết quá trình lưu trong nền đã bắt đầu và kết thúc thành công với một PID cụ thể.

Mẹo chuyên nghiệp để tăng tính ổn định cho Redis- Tắt Transparent Huge Pages (THP): THP thường khiến mức sử dụng bộ nhớ tăng gấp đôi hoặc gấp ba trong quá trình fork(). Hãy tắt nó bằng cách chạy lệnh echo never > /sys/kernel/mm/transparent_hugepage/enabled để ngăn chặn hiện tượng tăng đột biến độ trễ.- Theo dõi phân mảnh bộ nhớ: Chạy lệnh redis-cli info memory và tìm chỉ số mem_fragmentation_ratio. Nếu chỉ số này trên 1.5, Redis đang gây lãng phí đáng kể RAM, khiến việc fork dễ bị thất bại hơn.- Thiết lập cảnh báo lưu trữ: Đừng đợi đến khi xảy ra sự cố mới biết việc lưu dữ liệu bị lỗi. Hãy theo dõi chỉ số rdb_last_bgsave_status; nếu nó không phải là 'ok', dữ liệu của bạn đang gặp nguy hiểm.

Related Error Notes