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ệnhfree -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ể.

