問題の概要Redisのログに「Can't save in background: fork: Cannot allocate memory」と出力されている場合、Linuxのメモリ管理に関する一般的な問題に直面している可能性があります。このエラーは通常、BGSAVEまたはBGREWRITEAOFコマンドの実行中に発生します。これが発生すると、Redisはデータスナップショットの作成を停止します。これは重大なリスクです。もし今サーバーがクラッシュした場合、最後の保存に成功した以降のすべての書き込み操作が失われる可能性があります。
根本原因Redisは、fork()を呼び出して子プロセスを作成することでデータの永続化を処理します。この子プロセスは**コピーオンライト (COW)**を使用して、親プロセスとメモリを共有します。これは効率的ですが、Linuxカーネルはしばしば過保護に動作します。デフォルトでは、カーネルは子プロセスが最終的に親プロセスと同じ量のメモリを必要とするという最悪のシナリオを想定し、十分なRAMがあるかどうかを推定します。
例えば、16GBのRAMを搭載したサーバーがあるとします。Redisが9GBを使用している場合、カーネルは合計使用量が物理RAMを超える18GBに達することを恐れて、fork()を拒否することがあります。たとえ子プロセスが実際には数百メガバイトの増分メモリしか必要としない場合でも、システム全体のクラッシュを防ぐためにリクエストをブロックします。
解決ステップ### ステップ 1: 現在のオーバーコミット設定を確認するまず、Linuxホストが現在どのようにメモリのオーバーコミットを処理しているかを確認します。次のコマンドを実行してください。
cat /proc/sys/vm/overcommit_memory
値が0の場合、カーネルはヒューリスティックなアプローチを使用しています。利用可能なシステムメモリの50%以上を使用しているRedisインスタンスにおいて、これがエラーの原因であることがほとんどです。
ステップ 2: メモリのオーバーコミットを即座に有効にする再起動やサービスの再起動なしで、即座に修正できます。オーバーコミットモードを1に設定します。これにより、カーネルはアプリケーションを信頼し、常にメモリ割り当てを許可するようになります。
sudo sysctl vm.overcommit_memory=1
適用後、手動で保存を実行して修正を確認します。
redis-cli BGSAVE
ステップ 3: 設定を永続化するsysctlコマンドによる変更は一時的なもので、再起動後にリセットされます。この変更を永続的にするには、システム設定ファイルを更新する必要があります。
- 設定ファイルを開きます:
sudo nano /etc/sysctl.conf- ファイルの末尾に次の行を追加します:vm.overcommit_memory = 1- 保存して終了します (Ctrl+O, Enter, Ctrl+X)。- 設定をリロードして、有効になっていることを確認します:sudo sysctl -p### ステップ 4: スワップ領域を評価するオーバーコミットを1に設定してもエラーが解消されない場合は、システムのリソースが本当に不足しています。free -mで現在の使用状況を確認してください。16GBのサーバーで空きメモリが100MBしかなく、スワップが0Bの場合、余裕を持たせる必要があります。4GBのスワップファイルを追加することで、fork時の短いスパイクに対するセーフティネットとして機能します。
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
確認保存を実行しながら、Redisのログをリアルタイムで監視して修正を確認します。2つのターミナルウィンドウを開いてください。
# ターミナル 1: ログを監視
tail -f /var/log/redis/redis-server.log
# ターミナル 2: 保存を実行
redis-cli BGSAVE
修正が成功すると、バックグラウンド保存が開始され、特定のPIDで正常に終了したことを示すログ行が出力されます。

