FreeBSD 11.1-STABLE을 사용하여 gzip-9 압축과 8K의 레코드 크기로 구성된 ZFS 데이터 세트가 있습니다. (이 볼륨은 속도가 아닌 작은 파일을 보관하는 데 사용됩니다.)
zfs get all pool02/redactedStorage
1.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%가 된다는 것을 보여줍니다.
차트에 따르면 이 경우 솔루션은 recordsize
12디스크 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=8K
19K의 디스크 사용량을 표시합니다 . 추가로 시도했지만 recordsize=64K
샘플 파일의 크기에는 아무런 영향이 없었습니다.
또한 new 아래에 파일 인스턴스를 생성하려면 cp
후자가 실제로 필요하다는 점에 유의하세요 .mv
recordsize
이 기사는 또한 무슨 일이 일어나고 있는지에 대한 좋은 설명을 제공하며, 이는 후손을 위해 남겨두겠습니다.
https://klarasystems.com/articles/choosing-the-right-zfs-pool-layout/
- 패딩, 디스크 섹터 크기 및 레코드 크기 설정:RAID-Z에서는 패리티 정보가 RAID-5처럼 특정 스트라이프가 아닌 각 블록과 연관되어 있으므로 너무 작아서 재사용할 수 없는 세그먼트가 해제되는 것을 방지하려면 각 데이터 할당이 p+1(패리티+1) 다중이어야 합니다. 할당된 데이터가 p+1의 배수가 아닌 경우 "패딩"이 사용되므로 RAID-Z는 RAID-5보다 패리티와 패딩 공간이 조금 더 필요합니다. 이는 복잡한 질문이지만 간단히 말해서 공간 비효율성을 방지하려면 ZFS 레코드 크기를 디스크 섹터 크기보다 훨씬 크게 유지해야 합니다. 512바이트 섹터 디스크의 경우 Recordsize=4K 또는 8K를 사용할 수 있습니다. 4K 섹터 디스크의 경우 Recordsize는 이 값의 몇 배여야 합니다(기본값 128K이면 충분함). 그렇지 않으면 너무 많은 공간을 잃게 될 수 있습니다.