====== 今更ながらZFSはキャッシュのヒット率が超重要 ======
この記事には技術的裏付けがない、個人の感想、雑感、推測がふんだんに含まれています。ご利用の際は用法・用量を守り正しくお使いください。
知人のNAS4Freeなファイルサーバが重い問題、[[blog:2017:2017-08-04|Sambaが原因]]で一件落着かと思いきや解決してなかった。(こっちはこっちで別の問題が発生してたりするので別途書く予定。)
知人とやり取りしつつCPU, ネットワーク, ディスクI/O, その他諸々を継続的にモニタリングしてみると、どーにもディスクアクセスがボトルネックになっている事があるようで…。ファイルサーバのターミナルで直接cpしても、全然速度が上がらないのだ。対象のファイルは、50~200kBの数十万個のPNGを含む膨大なファイル群で、ファイルシステム的に結構厳しい条件ではあるものの、ストレージは仮にもHDD 2ペア×3セットからなるRAID10である。十数MB/sは出るだろうと思ってたが、実際には1MB/s以下になることさえある。
いくらなんでもオカシイだろうとzpool iostatしてみた結果がこちら。
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
zdata 4.56T 6.31T 5.65K 435 25.5M 4.94M
zdata 4.56T 6.31T 7.43K 0 32.7M 0
zdata 4.56T 6.31T 5.44K 0 24.1M 0
zdata 4.56T 6.31T 6.20K 0 27.3M 0
zdata 4.56T 6.31T 6.44K 0 28.4M 0
zdata 4.56T 6.31T 5.81K 398 26.6M 3.89M
zdata 4.56T 6.31T 4.36K 215 34.8M 10.8M
zdata 4.56T 6.31T 2.76K 391 12.5M 3.47M
zdata 4.56T 6.31T 3.58K 0 19.7M 0
zdata 4.56T 6.31T 3.65K 0 20.1M 0
zdata 4.56T 6.31T 3.15K 0 17.7M 0
zdata 4.56T 6.31T 4.05K 0 19.0M 0
zdata 4.56T 6.31T 2.59K 343 14.6M 3.15M
zdata 4.56T 6.31T 3.66K 0 19.6M 0
zdata 4.56T 6.31T 4.99K 0 32.5M 0
zdata 4.56T 6.31T 2.93K 0 19.1M 0
zdata 4.56T 6.31T 6.38K 0 28.4M 0
zdata 4.56T 6.31T 3K 344 13.6M 2.99M
zdata 4.56T 6.31T 3.86K 0 17.9M 0
zdata 4.56T 6.31T 3.77K 0 16.9M 0
zdata 4.56T 6.31T 3.72K 0 16.8M 0
zdata 4.56T 6.31T 2.91K 226 13.3M 2.39M
読み込み操作数(operations)と読み込み量(bandwidth)の割に、書き込み量が著しく少ない。コピーと並行してSambaへ断続的なアクセスがあるってことを差し引いても全然スループットが出てない。つーか、書き込み量とネットワークに出ていく量を合わせても全然読み込み量に足らん罠。
大量の読み込みoperationsが走ってても、いい感じに処理できてる時は↓こんな感じで順当にbandwidthが上がる。CIFSによるリクエスト分がそのまま処理されてネットワークに流れていっている。
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
zdata 4.70T 6.17T 15.3K 638 64.8M 7.06M
zdata 4.70T 6.17T 23.8K 0 101M 0
zdata 4.70T 6.17T 20.4K 0 85.9M 0
zdata 4.70T 6.17T 23.6K 0 98.7M 0
zdata 4.70T 6.17T 18.4K 0 76.5M 0
zdata 4.70T 6.17T 7.06K 720 30.1M 8.41M
zdata 4.70T 6.17T 16.6K 0 70.0M 0
zdata 4.70T 6.17T 13.7K 0 57.7M 0
zdata 4.70T 6.17T 18.1K 0 77.3M 0
zdata 4.70T 6.17T 16.7K 536 72.3M 6.52M
zdata 4.70T 6.17T 7.63K 80 32.5M 376K
zdata 4.70T 6.17T 12.3K 0 52.7M 0
zdata 4.70T 6.17T 9.78K 0 42.4M 0
zdata 4.70T 6.17T 11.8K 0 51.0M 0
zdata 4.70T 6.17T 9.32K 586 40.4M 6.41M
zdata 4.70T 6.17T 9.47K 0 40.6M 0
zdata 4.70T 6.17T 11.6K 0 49.2M 0
zdata 4.70T 6.17T 12.1K 0 51.8M 0
zdata 4.70T 6.17T 5.05K 0 22.2M 0
zdata 4.70T 6.17T 4.88K 579 22.1M 6.61M
rsyncでディスク内コピーを行うと更に悲惨で、びっくりするほど速度が出ない。ネットワーク(1000BASE-T)越しの別マシンにzfs sendし、そいつとrsyncで同期した方が早いっていうね…。すわ、断片化か!?と思ったけど、プールは半分以上空いてるしちょっと考えにくい。
あれこれ考えてるうちに、ZFSはキャッシュのヒット率が重要って事を思い出した。1フォルダに大量の細かなファイルがあるって事は、その分メタデータ処理が重いと考えられる。とすれば、メタデータを使いまくってそうなrsyncで速度が出ないってのも説明が付く………気がしなくもない。
zfs-statsを入れてキャッシュのヒット率を見てみたら、なんと2割を切ってるじゃないの。キャッシュに乗り切らなかったメタデータに毎度アクセスしに行くために、read operationsの割にbandwidthが上がらなかったのかしら…?
とりあえずarc関連のカーネル変数を調整したところ、いい感じでキャッシュヒットするようになった。問題のプール内のディレクトリ間でrsyncした時の結果が↓これ。
{{ :blog:2018:monitering_zfs_cache.png |}}
キャッシュヒット率が90%ほどに改善し、書き込みも12MB/s程出ている(zdata iostatは1秒毎、vfs.zfs.txg.timeout=5である)。