Linuxのslabキャッシュが増加する原因と対処法を徹底解説

freeコマンドでメモリ使用量を確認したら、あやしいプロセスが見当たらないのにメモリが圧迫されていた」
/proc/meminfoを見たらSlabの値が異常に大きかった」
――LinuxサーバーでこのようなトラブルはSRE・インフラエンジニアなら一度は経験する問題です。

この記事では、slabキャッシュの仕組みから増加する代表的な原因、確認コマンド、対処法まで順を追って解説します。


スポンサーリンク

slabキャッシュとは?

slabキャッシュとは、Linuxカーネルがメモリを効率的に管理するための仕組みです。

Linuxにおいて、ページサイズ(通常4KB)未満の小さなメモリブロックはSLABアロケータによって管理されています。
SLABアロケータは、同じサイズのメモリオブジェクトをまとめてキャッシュしておくことで、都度のメモリ確保・解放にかかるコストを下げています。

特にヘビーユーザーになるのが、以下の2つのカーネルオブジェクトです。

  • dentryキャッシュ:ファイル名やディレクトリパスと inode を結びつける情報をキャッシュする
  • inodeキャッシュ:ファイルのメタデータ(パーミッション・サイズ・タイムスタンプなど)をキャッシュする

これらはファイルシステムのパフォーマンスに直結するため、Linuxカーネルは積極的にキャッシュします。
メモリが潤沢なうちは増え続けるのが正常な動作ですが、適切に回収されずに増加し続けるケースが問題になります。


/proc/meminfo でのSlabの見方

slabキャッシュの使用量は /proc/meminfo から確認できます。

cat /proc/meminfo | grep -E "Slab|claim"

出力例:

Slab:            1843200 kB
SReclaimable:    1600000 kB
SUnreclaim:       243200 kB
項目意味
Slabslabキャッシュ全体(SReclaimable + SUnreclaim)
SReclaimableメモリ不足時に回収可能なslabキャッシュ
SUnreclaim回収不可能なslabキャッシュ

重要なのはSUnreclaimが増え続けていないかという点です。
SReclaimableが大きい場合は、メモリが逼迫すればカーネルが自動で回収するため、ある程度は正常です。
一方SUnreclaimが増加し続ける場合はカーネルのメモリリークを疑う必要があります。

SUnreclaimの値がシステム総メモリの10%を超える場合は、slabのメモリリークが発生している可能性があります。

slabtopで詳細を確認する

どのキャッシュが肥大化しているかは slabtop コマンドで確認できます。

sudo slabtop

使用量の多い順に表示されるため、上位に dentryinode_cacheext4_inode_cache などが並んでいるかどうか確認してください。
/proc/slabinfo を直接参照することも可能です。

cat /proc/slabinfo

slabキャッシュが増加する主な原因

原因1:大量ファイルへのスキャン(dentryキャッシュ肥大化)

slabキャッシュ増加の原因として最も多いのが、大量のファイルを持つサーバーでのファイルスキャンです。

find コマンドや updatedb コマンドがファイルシステム全体を走査すると、すべてのパスに対応するdentryオブジェクトとinodeオブジェクトが生成されます。
これが一気に大量生成されたあと、SLABアロケータの特性により解放が遅れる「フラグメンテーション」が発生します。

SLABフラグメンテーションとは、大量のメモリ確保が連続して起きたあとに解放が連続して起きると、部分的に使用中のページが大量に残る現象です。
この状態では、見かけ上はメモリを使用しているのに、実際に有効なデータはごく一部しか入っていないという状況になります。

典型的なトリガーとなるコマンド・処理:

  • find / -name "..." による広範囲のファイル検索
  • updatedb(mlocateデータベースの更新)の定期実行
  • バックアップツールによるファイルシステム全体の走査
  • ログファイルを検索するバッチ処理

mlocate(updatedb)による増加

RHEL・CentOS・Amazon Linux 2 などのディストリビューションでは、デフォルトで /etc/cron.daily/mlocate が設定されており、毎日 updatedb コマンドが自動実行されます。

大量のファイルを抱えるGitサーバーやファイルサーバーなどで、これが毎朝決まった時間帯にslabキャッシュを急増させる原因になることがあります。

確認方法:

cat /etc/cron.daily/mlocate

対策として、/etc/updatedb.confPRUNEPATHSPRUNEFS に除外パスを追加してスキャン対象を絞り込むことができます。


原因2:大量の一意なファイルの生成と削除(negative dentry)

アプリケーションが短時間に大量のユニークなファイル名でファイルを作成・削除しているケースでも、dentryキャッシュが肥大化します。

これは negative dentry(ネガティブdentry) の増加が原因です。
negative dentry とは、「このパスのファイルは存在しない」という情報をキャッシュしたdentryエントリです。

ファイルを削除したあとも、カーネルはそのパスに対するnegative dentryを保持し続けます。
毎時数千〜数万のユニークなファイルを生成・削除するようなアプリケーション(例:一意なファイル名でのキャッシュ生成)では、このnegative dentryが急速に蓄積します。

sar -v コマンドで dentunusd(未使用のdentryキャッシュエントリ数)を確認できます。

sar -v

原因3:ログファイルの蓄積

ログファイルが削除されずに大量に蓄積しているサーバーでは、それらのログを走査するバッチ処理のたびにdentryキャッシュが増加します。

特にログファイルの命名規則が YYYYMMDD でなく YYYYMMDDhhmm のような形式の場合、既存のバッチの削除対象に含まれず、ファイルが際限なく増え続けることがあります。
そのバッチがファイルを検索するたびに、全ファイルのdentry・inodeが生成されキャッシュとして残ります。


原因4:SUnreclaimの増加(カーネルメモリリーク)

SUnreclaim が増加し続ける場合は、カーネルコンポーネントやカーネルモジュールのメモリリークが疑われます。

カーネルコンポーネントやドライバーは kmalloc などのインターフェイスを通じてslabアロケータにメモリをリクエストします。
これらが適切にメモリを解放しないと、回収不能なslabが増え続けます。

slabtop で上位に kmalloc-* 系のエントリが大量に表示される場合、このパターンが疑われます。

調査には crash ツールや perf ツールを使ったより詳細なカーネル解析が必要になります。
解決策としては、カーネルのアップデートまたは問題のあるモジュールの修正・入れ替えになります。


確認手順まとめ

増加しているslabキャッシュの原因を特定する手順は以下のとおりです。

  1. /proc/meminfoSReclaimableSUnreclaim の割合を確認する
  2. slabtop で使用量の多いスラブ名(dentryinode_cache など)を特定する
  3. SReclaimable が主因なら、ファイルスキャン系のバッチ・cronがないか確認する
  4. SUnreclaim が主因なら、カーネルのメモリリークを疑い crash ツールで調査する
  5. sar -vdentunusd(negative dentryの数)を確認する

対処法

一時的な解放:drop_caches

回収可能なslabキャッシュ(SReclaimable)は、以下のコマンドで手動解放できます。

# slabオブジェクト(dentry・inodeを含む)の解放
echo 2 > /proc/sys/vm/drop_caches

# ページキャッシュとslabオブジェクトの両方を解放
echo 3 > /proc/sys/vm/drop_caches

⚠️ 注意: drop_caches はあくまでも一時的な対処です。
ダーティデータ(まだディスクに書き込まれていないデータ)は解放されませんが、実行前に sync コマンドでディスクへの書き込みを完了させることを推奨します。
また、直後に再びキャッシュが蓄積する場合は、根本原因の対処が必要です。

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

カーネルパラメータの調整:vfs_cache_pressure

vm.vfs_cache_pressure は、カーネルがdentry・inodeキャッシュを積極的に回収しようとする度合いを制御するパラメータです。

挙動
デフォルト(100)ページキャッシュと同程度の優先度で回収
100未満dentry・inodeキャッシュを保持しやすくなる
100超より積極的にdentry・inodeキャッシュを回収する

slabキャッシュの増加が問題になる環境では、値を大きくすることで改善が見込めます。

# 一時的に変更
sudo sysctl -w vm.vfs_cache_pressure=500

# 永続化(/etc/sysctl.confに追記)
echo 'vm.vfs_cache_pressure=500' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

根本対処:スキャン対象の絞り込みと不要ファイルの削除

slabキャッシュ増加の根本原因がファイルスキャンである場合、最も有効な対処は以下のとおりです。

  • 蓄積したログファイル・一時ファイルを削除する
  • updatedb/etc/updatedb.conf でスキャン対象パスを除外する
  • バッチ処理のファイル検索範囲を絞り込む
  • ファイルの命名規則を統一して削除バッチが確実に動作するようにする

まとめ

Linuxのslabキャッシュが増加する主な原因は以下の4つです。

  • findupdatedb などによる大量ファイルへのスキャン(dentryキャッシュ肥大化)
  • 大量のユニークファイルの生成・削除によるnegative dentryの蓄積
  • ログファイルなどの蓄積によるバッチ処理の肥大化
  • カーネルコンポーネント・モジュールのメモリリーク(SUnreclaimの増加)

調査の第一歩は /proc/meminfoSReclaimableSUnreclaim を確認し、slabtop でどのスラブが膨らんでいるかを特定することです。
一時的な解放には drop_caches が有効ですが、根本原因の解消なしには再発します。
vfs_cache_pressure の調整や、スキャン対象の絞り込み・不要ファイルの削除が恒久対策になります。

Linuxのスワップ領域の仕組みと設定方法はこちらでも解説しています。


参考情報源:

コメント

タイトルとURLをコピーしました