最初にお断りするが、十分なメモリ、あるいはSSDをお持ちでない方は帰っていただいて結構です。
ZFSにはdedupという機能がある。
その機能を有効にすると、例えばここに1GBのファイルが一つあるとして、それをコピーしても、場所が同じpool内である限り、1GBのディスクしか消費しない。
何それただのハードリンクと思うのは早い。
仮に同一のファイルA, Bがあるとする。いずれも1GB。
ハードリンクすればディスク消費量は1GBだ。
さてここで、ファイルBの一部、1bitだけを変えたいとする。
もはやハードリンクはできず、別個のファイルとして扱うことになる。
したがってディスク消費は2GB。
ではdedupだとどうなるか。
1bit違う1GBのファイル二つがあっても、なんと1GBと128KBだけしかディスクを消費しないという驚きの仕組み。
どういうことかというと、dedupはファイルが同じかどうかをブロックごとに判断するということ。
先の例でいえば、異なる1bitを含むブロック分だけを追加で確保し、それ以外はファイルAと同じものを使う。
なお、ZFSでブロックサイズは512B~128KB。
つまり大目に見積もっても1GBと128KBだけの消費でよいわけ。
なぜそんなことができるのか。
ZFSはプール上にあるデータのすべてのブロックのハッシュをメモリ上に持っている。
あるファイルをディスクに書き込む前に、ファイルをブロックに分解しハッシュテーブルと照合、書き込み要否を判断するという仕組み。
問題はメモリ上に置くテーブルのサイズだ。
dedupを有効に使うには、テーブルを置けるほど十分なメモリが必要になる。
しかし、のちほど見積もりをするが、数TBのディスクを考えるとメモリで賄うのは少々厳しい。
当然、メモリをこればっかりに使うわけにもいかないのだし。
もちろん、テーブルをハードディスクに置くことはできるが、ファイルを書き込むたびにディスク上のハッシュテーブルを参照することになる。
つまりすっごく遅くなる。
よろしい。ならばSSDだ。
とはいえ、Dedupの目的がディスクの容量節約ならば、安いHDDケチってメモリ、SSD無理して買うのも本末転倒という話になってくる。
月並みだけど、よく考えた方がいいよね。
では仮に2TBのデータが詰まったZFSでDedupしたら、どれくらいのメモリが必要か。
ハッシュテーブルは1ブロックにつき320Bytes。
zfsのブロックサイズは512Bから128KBで可変。
ざっくり64KBとみなす。
では計算。
2TB=1024 * 1024 * 1024 * 2 = 2147,483,648KB。
2TB/64KB=33,554,432 blocks
2TBは33,554,432 blocks。
1blockあたり320Bytesなので、かければテーブルに必要なサイズが出る。
33,554,432 blocks * 320 Bytes = 10,737,418,240 = 10GBytes
はい解散。
と言いたくなるレベルですな。
念のため記載するが、上記は2TBのデータを使っているときのdedupテーブルの試算。
2TBのプールに100bytes程度のファイル一つ置いただけなら、ハッシュテーブルは320Bytes程度。
そもそも2TB全部にDedupするのが間違いであった。
Dedupを活かしたいなら、扱うファイルで決めるのも手。
ざっくり言えばオフィスドキュメント、仮想マシンイメージなど、重複が見込まれるファイルを多く保管するディレクトリに対してのみDedupするとよいでしょう。
一方で動画などはあまり有効ではないでしょう。
なお、プールでDedupするとどれくらい得か、というのは調べることができる。
zdbにプール名を与えてやればいい。
一番下に重複具合が表示される。以下の例では1.06。あまり意味はないってことですな。
ちなみに、あるプールに同一のファイルを3つだけ置くとここが3.00になる。
$ sudo zdb -S vault
パスワード:
Simulated DDT histogram:
bucket allocated referenced
______ ______________________________ ______________________________
refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE
------ ------ ----- ----- ----- ------ ----- ----- -----
1 8.22M 1.02T 1.02T 1.02T 8.22M 1.02T 1.02T 1.02T
2 406K 50.6G 50.6G 50.6G 815K 102G 102G 102G
4 185 17.1M 17.1M 17.1M 835 73.6M 73.6M 73.6M
8 146 14.2M 14.2M 14.2M 1.75K 182M 182M 182M
16 17 8.50K 8.50K 8.50K 407 204K 204K 204K
32 150 16.7M 16.7M 16.7M 5.43K 600M 600M 600M
64 9 132K 132K 132K 820 9.49M 9.49M 9.49M
128 6 3K 3K 3K 1.02K 521K 521K 521K
256 3 129K 129K 129K 884 40.5M 40.5M 40.5M
64K 1 128K 128K 128K 73.4K 9.18G 9.18G 9.18G
Total 8.62M 1.07T 1.07T 1.07T 9.10M 1.13T 1.13T 1.13T
dedup = 1.06, compress = 1.00, copies = 1.00, dedup * compress / copies = 1.0
まあzfs set dedup=ONとかすればいいんだけど、現状使う予定もないので詳しく調べてない。