結論から先に。SQLite3データベースファイルなど、数GB単位のファイルに seek/read/write を頻繁に繰り返してスナップショットをしっかり取りたい用途なら ZFS volume 上に UFS を構築するのがよろし。
zfsは速いと言う人と遅いと言う人がいる。どちらも正解だと思う。 メモリ潤沢マシンで、ソースプログラムとかの細かい ファイルの詰まった tar.gz ファイルなんかを展開するときは超快適だし、 メモリを使い切ってしまったあとなど遅い。
SQLite3にデータを蓄積するSNSを運用していて、既に5年目の現在 データファイルが6GBに達した。3GBを超えたあたりから読み込みの 時間が気になるようになり、SSDを足してzfsのキャッシュ(L2ARC)にあてがって 許容できるレベルを保てている。と思っていた。 がしかし、リブート後のメモリキャッシュが 効いていない状態ではL2ARCがあっても壊滅的に遅い。
-rw-r----- 1 s4 wheel 6236690432 Oct 26 10:41 db.sq3
こんな感じのファイルを sum コマンドで全域舐める時間を計った(実運用機 なのでリブートは気軽に試せず数値は超アバウト)。
種別 | メモリキャッシュあり | なし |
---|---|---|
zfs on HDD | 1分半 | 4分〜10分 |
zfs on SSD | 30秒 | 20秒 |
ufs on HDD | 8秒 | 1分10秒 |
サーバの負荷によって値がグルグル変わるので全くもって信頼できない 値だが、zfs on HDDがどんなに頑張ってもufsに勝てないのは間違いない。
ちなみにsumコマンドで読ませているときにtopでプロセス状態を見ると 大概こんな感じ。
28974 s4 1 22 0 10M 2312K zio->i 4 0:06 2.84% sum
zio->i でピタっと止まり、全然CPUが働けてない。
さて、UFSの方が巨大ファイルのシーク+IOが速いことが分かったので それにしたい。だが、zfsでスナップショットをとりまくってデータロスへの 安全弁をたくさん作っているのでUFSだとちと面倒。UFSでも mksnap_ffs(8) でスナップショットを作れるのだが、これ、20世代までしか作れないのが落し穴。
どしたらええの?
新たにUFSデバイスなんか追加できないのでzvolでufsを作ってみたところ これが意外に行けそう。
zfs create -V 32G zpool/ufs0 newfs -U zvol/zpool/ufs0 mount -t ufs zvol/zpool/ufs0 /ufshome
snapshotはどうやって取ろうか?
mksnap_ffsで取ったスナップショットを世代管理してrsync --link-dest でリモートに世代バックアップするスクリプトは作ってあるので、それでやるか もしくは、zfs snapshot で zfs volume をバックアップするか、 いずれにしても、zfsそのもののファイルシステムでのスナップショットより 手間は掛かりそうだ。