web-dev-qa-db-ja.com

forkがメモリを割り当てることができないため、redis bgsaveが失敗しました

all:「free -m」を使用したサーバーのメモリ情報です。

              total       used       free     shared    buffers     cached
 Mem:         64433       49259      15174          0          3         31
 -/+ buffers/cache:      49224      15209
 Swap:         8197        184       8012

私のredis-serverは46Gのメモリを使用しましたが、ほぼ15Gのメモリが残っています

私の知る限り、forkは書き込み時のコピーであり、15Gの空きメモリがあれば必要です。これは必要なカーネル構造をmallocするのに十分です。

また、redis-serverが42Gメモリを使用した場合、bgsaveは問題なく、forkも問題ありません。

Forkが成功を返すように調整できるvmパラメーターはありますか?

44
Jim Gray

proc(5) manページから:

/ proc/sys/vm/overcommit_memory

このファイルには、カーネル仮想メモリアカウンティングモードが含まれています。値は次のとおりです。

0:ヒューリスティックなオーバーコミット(これがデフォルトです)

1:常にオーバーコミット、チェックしない

2:常に確認し、オーバーコミットしない

モード0では、MAP_NORESERVEが設定されたmmap(2)の呼び出しはチェックされず、デフォルトのチェックは非常に弱く、プロセスが「OOM-killed」になる危険性があります。 Linux 2.4では、ゼロ以外の値はモード1を意味します。モード2(Linux 2.6以降で使用可能)では、システム上の合計仮想アドレススペースは(SS + RAM *(r/100))に制限されます。SSはサイズですRAMは物理メモリのサイズ、rはファイル/ proc/sys/vm/overcommit_ratioの内容です。

26
Utoah

具体的には、 Redis FAQ

Redisバックグラウンド保存スキーマは、最新のオペレーティングシステムのフォークのコピーオンライトセマンティックに依存しています。Redisは、親の正確なコピーであるフォーク(子プロセスを作成)をフォークします。子プロセスはディスク上のDBをダンプし、最終的に終了します。理論上、子はコピーである親と同じ量のメモリを使用する必要がありますが、実際には、最新のオペレーティングシステムで実装されたコピーオンライトセマンティックのおかげで、親と子プロセスは共通メモリページを共有します。ページは、子または親で変更された場合にのみ複製されます。理論上、子プロセスの保存中にすべてのページが変更される可能性があるため、Linuxは子が使用するメモリ量を事前に判断できないため、overcommit_memory設定がゼロに設定されている場合、空きRAM必要に応じて、すべての親メモリページを実際に複製します。その結果、3 GBのRedisデータセットと2 GBの空きメモリしかない場合、失敗します。

Overcommit_memoryを1に設定すると、Linuxはより楽観的な割り当て方式でリラックスしてフォークを実行するようになります。これがRedisに必要なことです。

Redisは、OSがディスクへの書き込みに必要と考えるほど多くのメモリを必要としないため、フォークを先制的に失敗させる可能性があります。

74
Jeff Atwood

変更/etc/sysctl.confおよび追加:

vm.overcommit_memory=1

次に、次を使用してsysctlを再起動します。

FreeBSDの場合:

Sudo /etc/rc.d/sysctl reload

Linuxの場合:

Sudo sysctl -p /etc/sysctl.conf
58
Ganesh Krishnan