ZFS - 압축 파일이 디스크 사용량을 겉보기 크기의 거의 두 배로 표시하는 이유는 무엇입니까?

ZFS - 압축 파일이 디스크 사용량을 겉보기 크기의 거의 두 배로 표시하는 이유는 무엇입니까?

FreeBSD 11.1-STABLE을 사용하여 gzip-9 압축과 8K의 레코드 크기로 구성된 ZFS 데이터 세트가 있습니다. (이 볼륨은 속도가 아닌 작은 파일을 보관하는 데 사용됩니다.)

zfs get all pool02/redactedStorage1.4배의 압축률을 보여주네요. 생각보다 나쁘지만, 거기에는 텍스트 파일과 압축 파일이 섞여 있어서 크게 신경쓰일 정도는 아닙니다. 그런 다음 이 데이터세트에 저장된 일부 대용량 zip 파일을 보고 혼란스러웠습니다.

du -h및 의 출력은 du -hA압축 파일에 대해 예상한 것과 다릅니다.

예를 들어, 40MB의 0 파일은 디스크 공간을 거의 차지하지 않을 것으로 예상됩니다.

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

그러나 40MB의 임의 파일은 압축이 불가능하므로(모든 실제적인 목적을 위해) 약 40MB의 디스크 공간을 소비할 것으로 예상됩니다. 하지만 거의 소모될 줄은 몰랐어요더블공간:

# 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이면 충분함). 그렇지 않으면 너무 많은 공간을 잃게 될 수 있습니다.

관련 정보