ZFS - 圧縮ファイルがディスク使用量を見かけのサイズのほぼ2倍にするのはなぜですか?

ZFS - 圧縮ファイルがディスク使用量を見かけのサイズのほぼ2倍にするのはなぜですか?

FreeBSD 11.1-STABLEを使用してgzip-9圧縮と8Kのレコードサイズで構成されるZFSデータセットがあります。 (このボリュームは速度ではなく小さなファイルを保持するために使用されます。)

zfs get all pool02/redactedStorage1.4倍の圧縮率を示しますね。思ったより悪いですが、そこにはテキストファイルと圧縮ファイルが混ざっていて大きく気になるほどで​​はありません。その後、このデータセットに保存されているいくつかの大容量zipファイルを見て混乱しました。

du -hとの出力は、du -hA圧縮ファイルに期待したものとは異なります。

たとえば、40MBのゼロファイルはディスク容量をほとんど占有しないと予想されます。

# dd if=/dev/zero of=testfile bs=4M count=10
# du -h testfile
512B    testfile
# du -hA testfile
 40M    testfile

ただし、40 MBのランダムファイルは圧縮できないため(すべての実用的な目的のために)約40 MBのディスク容量を消費すると予想されます。しかし、ほとんど消費されるとは知りませんでした。ダブルスペース:

# dd if=/dev/random of=testfile.rnd bs=4M count=10
# du -h testfile.rnd
 92M    testfile.rnd
# du -hA testfile.rnd
 40M    testfile.rnd

研究によると、間接ブロックは余分なスペースを消費するようです。

testfile(0)について:

Dataset pool02/redactedStorage [ZPL], ID 56, cr_txg 360697, 958G, 22881480 objects, rootbp DVA[0]=<0:9dd68959000:3000> DVA[1]=<0:14e1475b5000:3000> [L0 DMU objset] fletcher4 uncompressed LE contiguous unique double size=800L/800P birth=25863270L/25863270P fill=22881480 cksum=13497492df:14cc540c2b5f:e089aa02d6109:73afb0d244bcb42

    Object  lvl   iblk   dblk  dsize  lsize   %full  type
  22910497    3   128K     8K      0  40.0M    0.00  ZFS plain file
                                        168   bonus  System attributes
        dnode flags: USED_BYTES USERUSED_ACCOUNTED
        dnode maxblkid: 5119
        path    /testfile
        uid     0
        gid     1004
        atime   Wed Apr 19 00:08:20 2023
        mtime   Wed Apr 19 00:08:20 2023
        ctime   Wed Apr 19 00:08:20 2023
        crtime  Wed Apr 19 00:08:20 2023
        gen     25862395
        mode    100644
        size    41943040
        parent  17938432
        links   1
        pflags  40800000004
Indirect blocks:
    [ No Indirect blocks ]

testfile.rnd(任意性)の場合:

Dataset pool02/redactedStorage [ZPL], ID 56, cr_txg 360697, 958G, 22881480 objects, rootbp DVA[0]=<0:9dbfec9d000:3000> DVA[1]=<0:14ffe1461000:3000> [L0 DMU objset] fletcher4 uncompressed LE contiguous unique double size=800L/800P birth=25863170L/25863170P fill=22881480 cksum=13b3f2c021:15912a82ff8a:ebef1e0641453:7abda3903292dba

    Object  lvl   iblk   dblk  dsize  lsize   %full  type
  22910499    3   128K     8K  91.9M  40.0M  100.00  ZFS plain file
                                        168   bonus  System attributes
        dnode flags: USED_BYTES USERUSED_ACCOUNTED
        dnode maxblkid: 5119
        path    /testfile.rnd
        uid     0
        gid     1004
        atime   Wed Apr 19 00:16:47 2023
        mtime   Wed Apr 19 00:16:48 2023
        ctime   Wed Apr 19 00:16:48 2023
        crtime  Wed Apr 19 00:16:47 2023
        gen     25862495
        mode    100644
        size    41943040
        parent  17938432
        links   1
        pflags  40800000004
Indirect blocks:
    [ 5120 Indirect blocks redacted ]

それでは、間接ブロック5120個* 128K = 640Mで、これらのブロックが圧縮されて51.9Mのオーバーヘッドが発生しますか?

それでは、この問題を解決するための最良の方法は何ですか? レコードサイズの大きい新しいデータセットを作成し、コンテンツを別の場所に移動しますか?

私のデータセットパラメータは次のとおりです。

NAME                  PROPERTY              VALUE                      SOURCE
pool02/redactedStorage  type                  filesystem                 -
pool02/redactedStorage  creation              Mon Jan 28  1:03 2019      -
pool02/redactedStorage  used                  958G                       -
pool02/redactedStorage  available             15.1T                      -
pool02/redactedStorage  referenced            958G                       -
pool02/redactedStorage  compressratio         1.40x                      -
pool02/redactedStorage  mounted               yes                        -
pool02/redactedStorage  quota                 none                       local
pool02/redactedStorage  reservation           none                       local
pool02/redactedStorage  recordsize            8K                         local
pool02/redactedStorage  mountpoint            /mnt/pool02/redactedStorage  default
pool02/redactedStorage  sharenfs              off                        default
pool02/redactedStorage  checksum              on                         default
pool02/redactedStorage  compression           gzip-9                     local
pool02/redactedStorage  atime                 on                         default
pool02/redactedStorage  devices               on                         default
pool02/redactedStorage  exec                  on                         default
pool02/redactedStorage  setuid                on                         default
pool02/redactedStorage  readonly              off                        default
pool02/redactedStorage  jailed                off                        default
pool02/redactedStorage  snapdir               hidden                     default
pool02/redactedStorage  aclmode               passthrough                local
pool02/redactedStorage  aclinherit            passthrough                inherited from pool02
pool02/redactedStorage  canmount              on                         default
pool02/redactedStorage  xattr                 off                        temporary
pool02/redactedStorage  copies                1                          default
pool02/redactedStorage  version               5                          -
pool02/redactedStorage  utf8only              off                        -
pool02/redactedStorage  normalization         none                       -
pool02/redactedStorage  casesensitivity       sensitive                  -
pool02/redactedStorage  vscan                 off                        default
pool02/redactedStorage  nbmand                off                        default
pool02/redactedStorage  sharesmb              off                        default
pool02/redactedStorage  refquota              none                       local
pool02/redactedStorage  refreservation        none                       local
pool02/redactedStorage  primarycache          all                        default
pool02/redactedStorage  secondarycache        all                        default
pool02/redactedStorage  usedbysnapshots       0                          -
pool02/redactedStorage  usedbydataset         958G                       -
pool02/redactedStorage  usedbychildren        0                          -
pool02/redactedStorage  usedbyrefreservation  0                          -
pool02/redactedStorage  logbias               latency                    default
pool02/redactedStorage  dedup                 off                        inherited from pool02
pool02/redactedStorage  mlslabel                                         -
pool02/redactedStorage  sync                  standard                   default
pool02/redactedStorage  refcompressratio      1.40x                      -
pool02/redactedStorage  written               958G                       -
pool02/redactedStorage  logicalused           501G                       -
pool02/redactedStorage  logicalreferenced     501G                       -
pool02/redactedStorage  volmode               default                    default
pool02/redactedStorage  filesystem_limit      none                       default
pool02/redactedStorage  snapshot_limit        none                       default
pool02/redactedStorage  filesystem_count      none                       default
pool02/redactedStorage  snapshot_count        none                       default
pool02/redactedStorage  redundant_metadata    all                        default

zdb関連プールを示すいくつかの出力は次のとおりです。

ashift: 12このプールのデフォルトvdevをメモしてください。)

pool02:
    version: 5000
    name: 'pool02'
    state: 0
    txg: 25383030
    pool_guid: 1288056053628670413
    hostid: 3785389258
    hostname: 'redacted'
    com.delphix:has_per_vdev_zaps
    vdev_children: 1
    vdev_tree:
        type: 'root'
        id: 0
        guid: 1288056053628670413
        create_txg: 4
        children[0]:
            type: 'raidz'
            id: 0
            guid: 9072182531784548301
            nparity: 2
            metaslab_array: 49
            metaslab_shift: 37
            ashift: 12
            asize: 23978959699968
            is_log: 0
            create_txg: 4
            com.delphix:vdev_zap_top: 36
            children[0]:
                type: 'disk'
                id: 0
                guid: 17108175667375824896
                path: '/dev/gptid/e07bacd6-1224-11e9-98bd-90b11c29519f'
                whole_disk: 1
                DTL: 293
                create_txg: 4
                com.delphix:vdev_zap_leaf: 37
            children[1]:
                type: 'disk'
                id: 1
                guid: 6726950469173540573
                path: '/dev/gptid/e443f9f2-1224-11e9-98bd-90b11c29519f'
                whole_disk: 1
                DTL: 292
                create_txg: 4
                com.delphix:vdev_zap_leaf: 38
--------==== 10 ADDITIONAL PHY DISKS REDACTED ====---------            
    features_for_read:
        com.delphix:hole_birth
        com.delphix:embedded_data

答え1

4Kセクタ(合計12個)を持つ12個のディスクで構成されたvdevで8Kレコードをストライピングすることはashift悪い考えであり、多くのオーバーヘッドをもたらします。

OpenZFSから:

https://openzfs.github.io/openzfs-docs/基本概念/RAIDZ.html

これらの入力により、レコードサイズがセクタサイズ以下である場合、RAIDZのパリティサイズは同じ冗長性を持つミラーと実質的に同じです。たとえば、3つのディスクを持つraidz1(ashift = 12とrecords = 4K)の場合は、ディスクに次のものを割り当てます。

  • 4Kデータブロック1個

  • 4Kパディングブロック1個

利用可能なスペース比は50%で、デュアルミラーと同じです。

3つのディスクがあり、ashift = 12でレコードサイズ= 128Kのraidz1の別の例:

  • 総ストライプ幅は3です。

  • 1つのパリティブロックがあるため、ストライプは最大2つの4Kサイズのデータ​​部分を持つことができます。

  • それぞれ8Kデータと4Kパリティを含む128K / 2 = 64のストライプがあります。

したがって、この例の空き容量比は66%です。

RAIDZにディスクが多いほど、ストライプが広くなり、スペース効率が向上します。

このテキストの後には、画面をキャプチャしてここに含めると読み取れない図がありますが、セクタサイズの1倍または2倍のレコードサイズの場合、オーバーヘッドがRAIDZ2で67%になることを示しています。

チャートによると、この場合、ソリューションはrecordsize12ディスクRAIDZ2 vdevからパリティ+パディングコストが18%の256Kに増やすことです。 (recordsize比較すると、128Kの場合、24%のオーバーヘッドが発生します)。

しかし、それほど単純ではありません。 「クラシック」ファイルシステムでは、次のように初期選択である8Kがrecordsize正しいことがあります。recordsize最高固定ブロックサイズではなくブロックサイズ。しかし、recordsizeより大きなファイルと比較的小さいファイルについてはまだ不利益があります。

増加はrecordsize変更後に生成されたデータにのみ影響しますが、この場合、プールはスペースの6%しか消費されず、現在の圧縮率は1.4倍です。長期的な容量の問題を引き起こすことなく、既存のデータをそのまま維持できます。ただし、回復オーバーヘッドが必要な場合:

https://openzfs.github.io/openzfs-docs/パフォーマンスとチューニング/ワークロード Tuning.html

アプリケーションが他のレコードサイズでより良いパフォーマンスを発揮する必要があるため、レコードサイズを変更する場合は、そのファイルを再生成する必要があります。各ファイルにcpの後にmvがあれば十分です。または、完全な受信が完了したら、send / recvは正しいレコードサイズでファイルを再生成する必要があります。

相関プーリングの実際の実験では:

# zfs set recordsize=256K pool02/redactedStorage

# dd if=/dev/zero of=testfile256.40M.zeroes bs=1M count=40
# du -h testfile256.40M.zeroes
512B    testfile256.40M.zeroes

# dd if=/dev/random of=testfile256.40M.rnd bs=1M count=40
# du -h testfile256.40M.rnd
 40M    testfile256.40M.rnd

# dd if=/dev/random of=testfile256.8K.rnd bs=8192 count=1
# du -h testfile256.8K.rnd
 37K    testfile256.8K.rnd

ご覧のとおり、40Mファイルは大量の論理スペースを使用しています。しかし、8Kファイルは37Kのスペースを消費します!

したがって、recordsizeデータセットの内容に応じて調整する必要があります。

もちろん、128Kのデフォルト値recordsizeが最適なようですので、触れないでください。

# zfs set recordsize=128K pool02/redactedStorage
# cp testfile256.40M.rnd testfile128.40M.rnd
# du -h testfile128.40M.rnd
512B    testfile128.40M.rnd
# mv testfile128.40M.rnd testfile128.40M.rnd2
# du -h testfile128.40M.rnd2
 40M    testfile128.40M.rnd2

# cp testfile256.8K.rnd testfile128.8K.rnd
# mv testfile128.8K.rnd testfile128.8K.rnd2
# du -h testfile128.8K.rnd2
 19K    testfile128.8K.rnd2

これは、8Kテストファイルが19Kのディスク容量を使用しますが、必要なメタデータオーバーヘッドがあることを示しています。見ている非圧縮性既存のファイルサイズは<= 8Kで、すべてのファイルも元のファイルからrecordsize=8K19Kのディスク使用量を表示します。さらに試しましたが、recordsize=64Kサンプルファイルのサイズには何の影響もありませんでした。

また、newの下にファイルインスタンスを作成するには、cp後者が実際に必要であることに注意してください。mvrecordsize

この記事はまた、何が起こっているかについての良い説明を提供し、これは子孫のために残すでしょう。

https://klarasystems.com/articles/choosing-the-right-zfs-pool-layout/

  1. パディング、ディスクセクタサイズ、レコードサイズの設定:RAID-Zでは、パリティ情報はRAID-5のように特定のストライプではなく各ブロックに関連付けられているため、小さすぎて再利用できないセグメントが解放されるのを防ぐために、各データ割り当てはp + 1(パリティ+ 1)複数である必要があります。割り当てられたデータがp + 1の倍数ではない場合は「パディング」が使用されるため、RAID-ZはRAID-5よりも少しパリティとパディングスペースが必要です。これは複雑な質問ですが、簡単に言ってスペースの非効率性を防ぐために、ZFSレコードサイズをディスクセクタサイズよりはるかに大きく保つ必要があります。 512バイトセクタディスクの場合は、Recordsize = 4Kまたは8Kを使用できます。 4Kセクターディスクの場合、Recordsizeはこの値の数倍でなければなりません(デフォルトは128Kで十分です)。そうしないと、あまりにも多くのスペースを失う可能性があります。

関連情報