Help us understand the problem. What is going on with this article?

nginxのキャッシュ階層を深くしすぎてinodeが枯渇した

More than 5 years have passed since last update.

nginxのproxy_cache_pathの設定がよくなかったためにinodeが枯渇してエラーになったので、メモしておきます。

設定

以下のようにしていました。

proxy_cache_path  /var/nginx/cache levels=2:2:2 keys_zone=hoge:10m inactive=10m max_size=100m;

levels

今回の現象に関係あるlevelsについて説明します。

levelsはキャッシュファイルのディレクトリ階層を設定するパラメータです。
levels=2:2:2だと「2文字を3階層」になります。

キャッシュのキーのMD5がb7f54b2df7773722d382f4809d65029cの場合だと、キャッシュのファイルのフルパスは以下のようになります。

/var/nginx/cache/9c/02/50/b7f54b2df7773722d382f4809d65029c

この設定により、ひとつのディレクトリに全キャッシュファイルを置くのではなく、ディレクトリを作って複数のディレクトリに分散させてファイルを置いていくことができます。

これは、Linuxのファイルシステムのひとつであるext3で、ひとつのディレクトリにファイルを大量に置くとパフォーマンスが低下する問題への対応策だと思われます。

Linuxにはあまり詳しくないので、指摘等あればコメントお願いします。

パラメータの詳細についてはnginxのドキュメントを見てください。

ディレクトリ数

それならばファイルが複数ディレクトリになるべく分散したほうが良いと考えてlevels=2:2:2にしていました。

さて、MD5のHEX文字列から2文字のディレクトリを作るとすると00からffまでの256のディレクトリが作られます。

3階層だと256 * 256 * 256で最大16,777,216ものディレクトリが作られることになります。

max_size

proxy_cache_pathにはmax_sizeというパラメータがあり、キャッシュ全体のサイズの上限を管理しています。

キャッシュがこのサイズを超えると、最も使われていないファイルを削除してくれるようになっています。

ところが、この機構は空っぽになったディレクトリは削除しません。

max_sizeを小さい値に設定しておいてキャッシュのファイルが増えすぎないようにしてもディレクトリが残るので、inodeが消費されていく一方です。

inactiveによる削除についても同様です。

当初、キャッシュディレクトリの合計サイズを調べて「max_sizeを超えているのに削除されない」と思っていましたが、nginxが見ているのがキャッシュのファイルサイズだけのようなので、大量ディレクトリによるスペース消費は抑制できないためでした

まとめ

多階層のlevelsによって大量にディレクトリが作られることによって、inodeが枯渇してエラーになるという事態が発生してしまいました。

また仮にinodeに余裕があったとしても、1ディレクトリが4096バイトを使うので、16,777,216 * 4096で最大64GBを消費するので、場合によってはスペースが先に枯渇するかもしれません。

さて、階層を浅くすると、ファイルの分散の度合いは下がります。

ただし今はmax_size=100mにしているため、キャッシュの平均サイズが1KBと考えるとファイル数は10万程度までしか増えません。

このファイル数であれば「2文字1階層」の256ディレクトリでも、1ディレクトリ平均400ファイルになるので大丈夫そうです。

max_sizeを増やす可能性があるので、ひとまずlevels=2:2に設定を変更することになったのでした。

najeira
Software developer。Google Cloud(特にApp Engine)とFlutterのGoogle Developers Expert。好きな言語はGo。他Flutter/Dart, Android, iOS, Python。
michael-inc
マイケルはコミュニティサービスをつくる会社、「Community Builder」です。インターネットを通して人生がより豊かになるよう、人がつながる場所をつくりつづけます。
https://michael-inc.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした