LinuxでRAMメモリのキャッシュやスワップをクリア・解放する方法

こんにちは。WebエンジニアのHodaです。

Linuxではどのディストリビューションも効率的なメモリ管理がされています。しかし時折、特定のプロセスがメモリを大きく占有し、メモリリーク(スワップアウト)してパフォーマンスが落ちることがあります。その対応策として、RAMメモリのキャッシュを解放する手段があるので、ご紹介します。

Linuxでメモリキャッシュをクリアする方法

DebianにRedhat、どのディストリビューションにおいても、システムを再起動せずにメモリをクリアする方法があります。それは次の3つです。

ページキャッシュのみクリア

sync; echo 1 > /proc/sys/vm/drop_caches

dentryとinodesのクリア

sync; echo 2 > /proc/sys/vm/drop_caches

ページキャッシュとdentry、inodesのクリア

sync; echo 3 > /proc/sys/vm/drop_caches

sync はメモリキャッシュの内容をディスクへ流し込むコマンドです。そのあとの ; は、1行で複数のコマンドを順次実行するための区切り文字です。

echo~ で、 /proc/sys/vm/drop_caches1~3 の数字を書き込んでいます。 drop_caches に直接書き込むことで、アプリケーションやサービスを停止せずにメモリキャッシュをクリアすることができます。

... echo 3 > ... はページキャッシュとdentry、iノードの全てをクリアしますが、Linuxでどのようなサービスがそれらを使っているのかハッキリするまでは使わないほうがいいです。

キャッシュの説明 - Page cache、dentry、inodesとは

Linuxでは、一度ディスクから読み込まれた情報をメモリへ保管(キャッシュ)します。一旦メモリへキャッシュされると、2回目以降はそのキャッシュから情報を読み取るようになります。

メモリの読み書きはディスクの読み書きと比べて非常に速いため、一旦メモリへデータをキャッシュすることで、高速に処理することが可能です。しかしメモリには上限があるため、なんでもかんでもメモリへぽいぽいキャッシュされると、メモリの上限を超えた情報がスワップアウトしてパフォーマンスが落ちます。

キャッシュ領域には大きく ページキャッシュdentryiノード の3つがあります。

Page cache…ページキャッシュ

一度ディスクから読み込まれたファイルデータがこの領域に格納されます。

Dentry…ディレクトリエントリキャッシュ

ファイルのパス検索を高速化するために、ディレクトリのパス名を__dentry__という領域にキャッシュします。

inodes…iノード

ファイルの属性、例えばパーミッションや所属グループ、作成者、作成日時、サイズなどの情報を__i odes__と呼ばれる領域に保管し、キャッシュします。

メモリの使用状況を確認するコマンド

次のコマンドでメモリの使用状況が確認できるので、キャッシュの解放前後で使ってみると良いです。

vmstat -S m
free -m

スワップキャッシュをクリアする方法

スワップキャッシュは次のコマンドで解放できます。

swapoff -a && swapon -a

Swap cache…スワップキャッシュ

一度スワップアウト、またはスワップインしたデータを保持するキャッシュ。再度スワップ処理が発生した場合、スワップ処理が効率よく動作します。

Swap out…スワップアウト サーバーに負荷がかかって処理が追いつかなくなると、メモリの容量を超えた分を応急処置としてディスクで読み書きする。

Swap in…スワップイン

スワップアウトしたデータを再度メモリに読み込む操作のこと。

メモリキャッシュ解放の自動化

Cronで自動化することも可能です。しかしスクリプトの実行と同時に他のユーザーがアクセスしていると、サーバーがクラッシュしたり、データベースの破損に繋がる恐れがあるため、 本番環境では自動実行しない ことを推奨します。必要な時にだけ使いましょう。

シェルスクリプトを作成

clear_memory_cache.sh とでも名付けたファイルを作り、ページキャッシュとスワップキャッシュを解放するコマンドを記入します。

#!/bin/bash
# Note, I'm using "echo 1", because using "echo 3" is not recommended in production.
echo 1 > /proc/sys/vm/drop_caches && swapoff -a && swapon -a && printf '\n%!s(MISSING)\n' 'RAM-cache and Swap were cleared.'

一度手動で実行し、ちゃんと動作するか確認します。

bash clear_memory_cache.sh

スクリプトファイルのパーミッション変更

作成したスクリプトファイルのパーミッションを設定します。

chmod 755 clear_memory_cache.sh

Cronの設定

定期的にスクリプトを実行するためにCronジョブを設定します。ここでは毎日午前3時に実行されるようにします。

次のコマンドでCrontabを編集モードで開き

crontab -e

次のように記述します。 ~/clear_memory_cache.sh は実行したいスクリプトのパスとファイル名に置き換えてください。

0 3 * * * bash ~/clear_memory_cache.sh

まとめ

Linuxでメモリキャッシュをクリアする方法をまとめました。やったね!

/proc/sys/vm/drop_caches に1~3の数字を書き込むだけで済むので簡単ですが、本番環境では危険なので、必要な時にだけ使うように注意して実行しましょう。