ZFSのパフォーマンスは空き容量に大きく依存することは知っています。
プールの使用率を80%未満に抑え、プールのパフォーマンスを維持します。現在、プールが非常にいっぱいで、ビジー状態のメールサーバーなどでファイルシステムが頻繁に更新されると、プールのパフォーマンスが低下する可能性があります。プールがいっぱいになるとパフォーマンスが低下する可能性がありますが、他の問題はありません。 [...] 95〜96%の範囲のほとんど静的なコンテンツでも、書き込み、読み取り、再同期のパフォーマンスが低下する可能性があることに注意してください。 ZFS_Best_Practices_Guide、solarisinternals.com(archive.org)
ここで、ZFSファイルシステムvolume
をホストする10Tのraidz2プールがあるとします。次に、子ファイルシステムvolume/test
を作成し、5Tの予約を与えます。
次に、NFSごとに両方のファイルシステムを一部のホストにマウントし、いくつかの作業を実行します。残りの5Tはvolume/test
に予約されているため、volume
に5Tを超えて書き込むことができないことを理解しています。
私の最初の質問は、volume
マウントポイントに〜5Tを埋めると、パフォーマンスがどのように低下するのですか?そのファイルシステムには、ZFSのコピーオンライトやその他のメタスタッフのための空き領域がないため、ドロップしますか?または、ZFSはvolume/test
用に予約されたスペース内の空きスペースを使用できるため、同じままですか?
今度は2番目の質問です。次のように設定を変更すると違いはありますか? volume
にvolume/test1
とvolume/test2
の2つのファイルシステムが追加されました。両方に3T予約が与えられます(割り当てはありません)。今、7Tをtest1
に書き込みます。両方のファイルシステムのパフォーマンスは同じですか、それともすべてのファイルシステムで異なりますか?落ちるか、同じままか?
ありがとう!
はい。プールに空きスペースを確保する必要があります。それは主にコピーオンライトアクションとスナップショットのためのものです。使用率が約85%になると、パフォーマンスが低下します。あなたはより高く行くことができますが、明確な影響があります。
予約を台無しにしないでください。特にNFSの場合。それは必要はありません。多分zvolのためですが、NFSのためではありません。
しかし、混乱は見られません。 10Tの場合は、85%を超えないようにしてください。 quotasを使用して共有のサイズを適切に設定し、使用を制限します。または、クォータを使用せず、全体的なpoolの使用状況を監視します。
パフォーマンスの低下は、zpoolが非常にいっぱいか、非常に断片化されている場合に発生します。この理由は、ZFSで使用されるフリーブロック検出のメカニズムです。 NTFSやext3などの他のファイルシステムとは異なり、どのブロックが占有され、どのブロックが空いているかを示すブロックビットマップはありません。代わりに、ZFSはzvolを「メタスラブ」と呼ばれる(通常は200)より大きな領域に分割し、AVLツリーを格納します1 各メタスラブの空きブロック情報(空間マップ)の数。バランスのとれたAVLツリーにより、リクエストのサイズに適合するブロックを効率的に検索できます。
このメカニズムは規模の理由で選択されましたが、残念なことに、高度な断片化やスペースの利用が発生した場合にも、大きな問題であることがわかりました。すべてのメタスラブが大量のデータを運ぶとすぐに、プールが空のときの少数の大きな領域とは対照的に、空きブロックの多数の小さな領域が得られます。 ZFSが2 MBのスペースを割り当てる必要がある場合、適切なブロックを見つけるか、2 MBをより小さなブロックに分割する方法を見つけるために、すべてのメタスラブのスペースマップの読み取りと評価を開始します。もちろん、これには少し時間がかかります。さらに悪いのは、ZFSが実際にすべてのスペースマップを物理ディスクから読み取るため、I/O操作の全体のコストがかかるという事実です。 anyの書き込み。
パフォーマンスの低下が著しい場合があります。きれいな写真が好きな場合は、 Delphixでのブログ記事 を見てください。これは、(単純化されていながらまだ有効な)zfsプールからいくつかの数値を取り出したものです。私は恥知らずにグラフの1つを盗んでいます-このグラフの青、赤、黄、緑の線を見てください。これらの線は、それぞれ、書き込みスループットに対する10%、50%、75%、93%の容量のプールを表しています。時間の経過とともに断片化する間のKB /秒:
これに対する素早い修正は、伝統的にmetaslabデバッグモードです(設定を即座に変更するには、実行時にecho metaslab_debug/W1 | mdb -kw
を発行するだけです)。 。この場合、すべてのスペースマップはOS RAMに保持されるため、各書き込み操作での過度で高価なI/Oの必要性がなくなります。結局のところ、これは、特に大きなプールの場合は、より多くのメモリが必要になることも意味するため、RAM for storage horse-trade。のようなものです。10TBプールおそらく2〜4 GBのメモリが必要になります2、しかしあなたはそれほど面倒なくそれを利用率の95%に追いやることができるでしょう。
1 少し複雑です。興味がある場合は、詳細については Bonwick's post on space maps を参照してください。
2 メモリの上限を計算する方法が必要な場合は、zdb -mm <pool>
を使用して各メタスラブで現在使用されているsegments
の数を取得し、2で除算して最悪のシナリオをモデル化します(各占有セグメントの後に空きセグメントが続きます)、これにAVLノードのレコードサイズを掛けます(2つのメモリポインターと1つの値、zfsの128ビットの性質と64ビットのアドレス指定は合計で32バイトになります)。人々は一般的に何らかの理由で64バイトを想定しているようですが)。
zdb -mm tank | awk '/segments/ {s+=$2}END {s*=32/2; printf("Space map size sum = %d\n",s)}'
参照:基本的な概要は zfs-discussメーリングリストでのMarkus Koveroによるこの投稿 に含まれていますが、彼は自分の計算でいくつかの間違いを犯したと思いますが、私はそれを訂正したいと思います。