Archive for the ‘Filesystem’ tag
LVMのSnapshotは直感的か?(ZFSとの比較有り)
現在、Linuxのファイルシステムのスタンダードと言えばext3に間違いないでしょう。しかしながらext3はext2との互換性を可能な限り保ちながらジャーナリング機能を追加するという基本設計です。なのでファイルシステムとしては少々古びており、技術的に最も優れているというわけではありません。最近ext4の安定板がkernel 2.6.28で利用可能となりましたが、ext4についてもext2からの設計を受け継いでいるため、それほど大きな機能追加や基本設計の変更というのは多くありません。
そんな中、Snapshot機能は差分バックアップとして効率的な考え方ですが、現在ファイルシステムでその機能をサポートしているものは多くありません。ext3もSnapshot機能は実装されておらず、実際LinuxでSnapshotを行うにはボリュームマネージャ(LVM)で行うことが最も手軽でポピュラーだと言えます。LVMのSnapshot機能はその使い方についてはそこら中に情報がありますが、実装についてはあまり知られていない気がします。僕もそこまで細かく見ているわけではありませんが、ユーザが往々にしてハマりそうなポイントをいくつかの例を見ながら挙げてみたいと思います。
あるLV, /dev/test/dataがあるとします。このLVのSnapshotをdata-snapとしてとります。dataの中のファイル, test.img (1Gbyte)をrmしたらどうなるでしょうか? 個人的な感覚では、test.imgのdata block情報がdata-snap領域にコピーされてからtest.imgが削除される。なのでdata-snapに確保してある領域が1Gbyte減る、と思います。
しかし実際にはdata-snapの領域はほとんど減りません。
また、dataの中にnew.img (1Gbyte)を新たに作成したらどうなるでしょうか? 個人的な感覚では、特段dataの中のデータを変更したわけじゃないのでdata-snapは関知しないのではと思います。
しかし実際にはdata-snapの領域は1Gbyte消費されます。何か納得いかない感じ。
つまりLVMのSnapshotはファイルシステムが実際にdata blockを更新したときにもとのblockをコピーするということに尽きる、という感じです。もし元のdata blockが空であっても。rmの場合はファイルシステムがdata blockを上書きするのはrm発行時ではなく、次にそのblockがファイルシステムによって確保されたときなので、それまではdata-snapの方にはそのデータはコピーされず、存続してるデータを参照し続けています。ある種効率的と言えば効率的です。でも、要は直感的でないのです。個人的には。
これに対し、先進的なファイルシステムの一つとしてZFSがあります。ZFSは現在Solarisのデフォルトファイルシステムとして採用されています。このファイルシステムは悔しいけど正直すごい。Linuxでもbtrfsってのが同じようなコンセプトで開発されていますが、こちらはまだunstableでkernel 2.6.29 rc1とかでようやくメインストリームにマージされた模様。かなり遅れをとっています。ZFSがすごいポイントは結構一杯あるので今回はSnapshotところに焦点を絞ります。ZFSはファイルシステムではあるものの同時にボリュームマネージャでもあります。ファイルシステムの機能でSnapshotが撮れてしまいます。そしてZFSのSnapshot実装はLinuxのLVMとは異なります。
先の2つの例では結果が逆になります。つまり、data中のファイルをrmした場合は即時data-snapの方にコピーされます。また、dataにファイルを新規作成した場合は関知しません。
LVMが「data blockを変更したらオリジナルのdata blockをコピーする」というスタンスであるのに対し、ZFSは「オリジナルのデータを維持する」というより上位の考え方で実装されている気がします。
*ちなみに上記data blockはより正確にはchunkということになると思われます。
個人的にはZFSの方が好きです。あとZFSが優れているのがrollbackをちゃんと備えているところですね。LVMは残念ながらrollback(もしくはrevert)を行うためのコマンドを用意していません。なのでリストアするには少し七面倒くさい手順が必要です。ZFSの場合はzfs rollback xxxxxとすれば一発でオリジナルのファイルシステムをSnapshotを撮ったときの状態に戻すことができます。うーむ、ZFS良すぎ。
この他にもとんでもいい機能がかなりありますがそれはまた機会があれば。最後にOpenSolarisのスクリーンショットを。結構カッコいいのよね。。
ファイルシステムのblock sizeを調べるには
OSの内部構造(メモリとかファイルシステムとか)を見ているといろんな単位がでてきます。
- セグメント
- ページフレーム
- ページ
- ブロック
- セクタ
等々。
ややこしい限りです。
たとえばページであれば現在のモダンなLinuxは4Kbyteが一般的です。
しかしファイルシステムのblock sizeとなるとデフォルト値はあるものの、ファイルシステム毎(ext2,ext3,jfs,xfs,reiserfs,ocfs2)にそのデフォルトが異なっていたりしますし、フォーマット時に指定可能な値なのでページサイズほど画一化されていません。よく使用するファイルサイズによって最適な値を選択するのがベストとされています。
なので「今このファイルシステムのblock sizeっていくつになってんの?」というのがわからなくなることがあります。そんなとき、ファイルシステムがext2またはext3であればtune2fsで調べることができます。
# tune2fs -l /dev/sda2 | grep "Block size" Block size: 4096
今回の/dev/sda2は4096byteつまり4Kbyteのblock sizeでフォーマットされていることがわかります。
しかしここで注意しておきたいのは、他のコマンドの出力結果がbyte単位ではなくてblock単位であったときこのファイルシステムのblock sizeとは一致しない可能性があることです。
たとえば、iostatをオプションなしで実行すると結果はblock単位で出力されますが、これは1blockあたり512byteとなっています。*ちなみに-kオプションをつけるとbyte単位で出力されます。
これは、iostatが言っているblockとは、実際にはセクタのことだからです。セクタはディスクデバイスにおけるデータ転送の最小単位で、基本的に512byteとなっているはずです。一方ファイルシステムが言うblockとはファイルシステムがデータを格納するときに確保する領域の最小単位です。したがって、セクタが512byteであり、保存するデータが512byteであったとしても、block sizeが4Kbyteでフォーマットされているファイルシステムでは4Kbyteの領域を消費してこのデータを格納します。ただし、実際はさらにこの無駄を排除するためにblockをフラグメント化して使うという機能が盛り込まれています。これは多分当初ext2では実装されていなかったのだと思いますが、現在はext2/ext3ともに実装されており、mke2fsの-fオプションでそのフラグメントのサイズを指定できます。
追記:フラグメントはext2/ext3ともに未実装のようです。-fオプションはダミーで実際には指定しても効果がありません。オイ!
追記:ためしに1Kbyteのファイル1000個と4Kbyteのファイルを1000個作ってみましたが、どちらも消費領域は4Mbyteでした。フラグメンテーション機能、やはりナス!
このようにOSの内部はいろんな単位が使用されており、さらにその値が時代(ソフトウェアのバージョン)によって違ったり、同じ言葉でも指すものが違ったりするのでなかなか厄介です。
Ext4, ついに安定版リリース
12/24にLinux kernel 2.6.28がリリースされました。このリリースの目玉としてExt4実装があります。Ext4はExt3と互換性を保ちながらも多くの改良がなされたものになっているようです。kernelnewbies.orgに記載されているNew featureを意訳してまとめてみました。
互換性
既存のExt3ファイルシステムはExt4にリフォーマットすることなく移行可能。具体的には該当ボリュームをReadOnlyでマウントしていくつかコマンド叩くだけでOK。
より大きなファイルシステムサイズ、ファイルサイズのサポート
Ext3からExt4ではそれぞれの制限は以下の通り。
ファイルシステムサイズ:16TB -> 1EB (エクサバイト)
ファイルサイズ:2TB -> 16TB
ちなみにEBとは、 (1 EB = 1024 PB, 1 PB = 1024 TB, 1 TB = 1024 GB)なぐらい大きい。
無制限のサブディレクトリ数
Ext3からExt4でのサブディレクトリ制限は以下の通り。
320000 -> 無制限
エクステントによる大きなファイル操作の効率化
これまでは「ファイル」のデータはディスクという円盤のいろんなところに「ブロック」としてバラバラと格納されていたが、このような大きなファイルを物理的に連続したブロック(これがエクステント)として格納するこで、特にdelete等の操作を効率化する。
マルチブロックアロケーションによる内部ブロック割当処理の効率化
これまでは連続してデータを書き込む際、ディスク上の空いているブロックを1ブロックずつ探してきて割り当てる、という処理になっていたがこれをブロックアロケータ自身に必要合計ブロック数を認識させることで、単一コールで複数ブロックを割り当てれるようになりオーバヘッドが緩和される。
遅延アロケーションによる性能改善
これまではデータが書き込まれるやいなやブロック割当てを実行していたが、これをしばらく遅らせることで連続データ書き込み時のブロック割当て処理をまとめて行えるようになりその分オーバヘッドが軽減できると同時にフラグメンテーションも抑えることができる。これは前述のエクステント、マルチブロックアロケーションと連携して相乗効果を発揮する仕組みになっている。
Fast fsck
fsckが対象とするinodeを全inodeから使用したinodeのみに絞り込むことでfsckにかかる所要時間を大幅に短縮する(環境によって1/2〜1/20程度に)。ただしinodeを使用したか未使用かを判断するにはfsckをその前後で走らせる必要があることに注意。
Journal checksum
ジャーナルの完全性を高めるためにチェックサム機構を取り入れた。これによって信頼性だけでなく、既存Ext3の2フェーズコミットをシングルコミットとすることができ性能の改善も期待できる(環境によっては20%程度向上の可能性も)。
オンライン・デフラグメンテーション
今回のkernelリリース(2.6.28)ではまだ実装していないが、将来のリリースではこのオンラインでのデフラグ機構が盛り込まれる予定。e4defragと呼ばれるツールで実装する。
inode関連の変更
ディレクトリ作成時にあらかじめinodeを作成しておくことにより、ファイル作成時のinode作成処理にかかるオーバヘッドを軽減する。
タイムスタンプを秒 -> ナノ秒に拡張。
上記にともないinodeのサイズを128バイトから256バイトに変更。
先行ディスク領域割当
アプリケーションがあらかじめ使用予定の領域を確保しておける仕組み。3つの利点があり、1つ目はアプリケーションが独自にこれを行おうとすると、あらかじめ領域を0で埋め尽くさなければ行けないがこれを回避できる。2つ目として、領域をあらかじめ一括して確保できるのでフラグメンテーションを抑制できる。3つ目として、必要な領域がなくなってしまうということがなくなることが挙げられる。
バリア機能がデフォルト有効に
ハードウェアが内部write-cacheをもって独自のキャッシュフラッシュ処理(順番入れ替え)を行うような場合でもジャーナルが確実にデータコミット前にディスクに書き込まれるように制御する。性能を若干犠牲にしてデータの完全性を高めるための選択。ただしマウント時に”mount -o barrier=0″とすることでこのバリアを無効にできる。
フーム、Ext4ではエクステント、マルチブロックアロケーション、遅延割当等を連携させて論理的に連続するデータを物理的にも連続させて管理やI/Oの効率化を計るところにかなり注力しているようです。素晴らしいー。
ZFSっていいんじゃないの
以前からちらほらと名前は聞いていたZFSですが、少し調べてみたところ相当良いのではと思いました。 ZFSはオープンソースとしてSun Microsystemsが開発しているファイルシステムで、もともとは将来のSolaris用に開発していたのを現在ではSolarisとは切り離して単独のオープンソースプロジェクトとして開発が進められている、というものです。
MacOS Xの次期バージョンでもオプショナルで採用予定とのことなのでこれを期に一気に認知度があがるんじゃないかなと思います。
さてこのZFS、何がいいのかというとまとめるとこんな感じ。
バックアップ、リストア関連
・フィアルシステムのスナップショット
・お気軽ロールバック
耐障害性関連
・同一Disk上でのデータ冗長化
柔軟性
・論理ドライブ、パーティションとかはもうナシ ひとつのストレージプールで表現
この中で特に僕がフムフムと思ったので柔軟性。
最近VA Linuxの高橋さんから「パーティションとかホントいらないよね」という話を聞いてなるほどーーっと思っていたところなのでこれは「おぉ、」と思いました。
要はパーティションでディスクを区切っちゃうと、シリンダの最後のパーティションなら容量を拡張することはなんとか可能ですが、真ん中くらいにあるパーティションの容量が足りなくなったりすると単純にそのパーティションを伸長することはできません。
これを「パーティションなんてもうナシよ。 ディスクはストレージプールで一括して抽象的に表現します」っていうのがZFS。 こうすることで、「オイオイ、予想外に/home足りねぇーぞ。 /home/nkjm使いすぎじゃね? /var死ぬ程余ってんのに。」ということがなくなります。
以下、www.opensolaris.orgより。
ZFS presents a pooled storage model that completely eliminates the concept of volumes and the associated problems of partitions, provisioning, wasted bandwidth and stranded storage. Thousands of filesystems can draw from a common storage pool, each one consuming only as much space as it actually needs. The combined I/O bandwidth of all devices in the pool is available to all filesystems at all times.
あとスナップショットによる高速インクリメンタルバックアップやロールバックとかも相当イイ! 来週は仕事してるフリしてZFSの検証でもしよっかなーー。 でも残念なことに今のとこLinuxにはportされてない模様。 検証するならopensolarisかFreeBSD上なのかな。 一応Linux向けには現在ZFS for FUSE/Linuxってのがあるみたい。
参考:
