OpenZFS 중복 제거 기능 개선, 사용 자제 권고
(despairlabs.com)- OpenZFS 2.3.0의 Fast Dedup은 기존 dedup보다 크게 나아졌지만, 일반 사용자가 기본값처럼 켜기에는 여전히 비용과 조건을 따져야 하는 기능임
- dedup은 이미 저장된 블록을 다시 쓰지 않고 참조만 늘리는 방식이라, 모든 쓰기·해제 경로에 dedup table 조회와 갱신 비용이 붙음
- 기존 방식은 ZAP 기반 테이블의 read-modify-write 증폭, 트랜잭션 동안 회수할 수 없는 live entry list, 이득 없는 unique entry 때문에 메모리와 IO 부담이 컸음
- Fast Dedup은 live entry를 424바이트에서 216바이트로 줄이고, dedup log, 점진적 flush,
zpool ddtprune,dedup_table_quota, DDT prefetch와 kstats로 운영자가 비용을 더 잘 통제하게 함 - 일반 워크로드에서는 실제 중복 블록이 적을 수 있고, OpenZFS 2.2의 BRT/block cloning이 더 낮은 비용으로 비슷한 절감을 제공하므로 dedup은 대량 중복 데이터와 zero-copy 대안 부재가 겹칠 때만 신중히 쓸 만함
OpenZFS dedup의 기본 동작
- 중복 제거(dedup) 는 OpenZFS가 데이터를 디스크에 쓰기 전에 같은 데이터가 이미 있으면 새 쓰기를 생략하고 기존 복사본에 참조를 추가하는 기능임
- 어려운 부분은 “이미 디스크에 있는지”와 “어디에 있는지”를 빠르게 알아내기 위한 정보를 계속 저장하고 조회해야 한다는 점임
- 이 정보를 담는 구조가 dedup table임
- 개념적으로는 데이터 체크섬을 키로, 디스크 위치와 참조 수(refcount)를 값으로 갖는 해시 테이블임
- 사용자 데이터가 아니라 pool metadata의 일부로 저장되는 구조적 pool 데이터임
쓰기·해제 경로에 붙는 비용
- dedup이 꺼져 있으면 OpenZFS는 metaslab allocator에서 공간을 할당받고, 반환된 DVA를 block pointer에 넣어 데이터를 씀
- dedup이 켜져 있으면 먼저 체크섬을 dedup table에서 조회함
- 항목이 없으면 새 공간을 할당하고 데이터를 쓴 뒤, refcount 1인 새 dedup entry를 만듦
- 항목이 있으면 기존 DVA를 block pointer에 복사하고 쓰기 IO를 완료 처리한 뒤 refcount를 늘림
- dedup으로 할당된 블록에는 block pointer에
D플래그가 설정됨- 해제 시
D플래그가 있으면 dedup table을 다시 조회하고 refcount를 줄임 - refcount가 0이 되면 dedup entry를 삭제하고 실제 공간을 해제함
- 해제 시
- 모든 쓰기와 해제가 dedup table 조회·갱신을 거치므로, dedup이 유용하려면 테이블 관리 오버헤드보다 실제 공간·IO 절감이 커야 함
기존 dedup이 나빴던 이유
-
ZAP 기반 dedup table의 증폭
- 기존 dedup table은 OpenZFS의 표준 온디스크 해시 테이블 객체인 ZAP을 사용함
- ZAP은 디렉터리, 속성 목록, 내부 관리에도 쓰이는 범용 구조지만 dedup entry 저장에는 잘 맞지 않음
- 일반적인 dedup entry는 40바이트 키와 압축 후 약 64바이트 값으로 구성되며, 32K ZAP block 하나에 약 188개의 일반 entry가 들어감
- OpenZFS는 부분 블록 쓰기와 제자리 덮어쓰기를 하지 않기 때문에, entry 하나를 갱신해도 전체 ZAP block을 읽고 수정한 뒤 새 블록으로 다시 써야 함
- 체크섬 키는 충돌 저항성이 강해야 하므로 임의의 두 entry가 같은 ZAP block에 가까이 배치될 가능성이 작고, 트랜잭션 내 여러 갱신이 같은 블록에 모일 가능성도 낮음
- RAM이 충분해 ARC가 dedup table을 계속 보유하면 읽기 비용은 줄어들지만, 이 때문에 dedup에는 많은 메모리가 필요하다는 오래된 권고가 생김
dedupvdev class는 충분히 크고 빠른 dedicated dedup vdev를 추가해 메모리 요구를 조금 줄일 수 있지만, dedup이 의미 있는 규모에서는 테이블 전체를 담을 크기와 충분한 속도가 필요함
-
live entry list의 메모리 사용
- OpenZFS는 트랜잭션 중 생성·수정된 dedup entry를 메모리의 live entry list에 보관함
- 같은 데이터가 같은 순간 여러 번 쓰일 때, 각 쓰기 스레드가 dedup table에 아직 없는 것으로 판단해 모두 새로 쓰는 상황을 막기 위한 구조임
- lookup은 먼저 live entry list를 확인함
- 해당 entry가 있으면 refcount를 늘림
- 없으면 “in progress” 상태의 live entry를 만들고 ZAP에서 실제 entry를 읽어온 뒤 “ready”로 바꿈
- 동시에 접근한 다른 쓰기 스레드는 ready가 될 때까지 대기함
- 트랜잭션 종료 시 live entry list를 순회해 관련 내용을 dedup ZAP에 반영함
- 기존 live entry는 하나당 424바이트였고, 이 메모리는 ARC가 아니라 kernel slab memory라 시스템 메모리 압박 시 회수할 수 없음
- live entry list는 트랜잭션마다 비워지지만, 한 트랜잭션에서 서로 다른 데이터를 많이 쓰면 peak가 커짐
-
unique entry가 테이블을 부풀림
- dedup은 디스크에 저장된 모든 블록을 추적하지만, 실제 이득은 refcount가 1보다 클 때만 생김
- refcount가 1인 unique entry는 언젠가 같은 데이터가 다시 쓰이기를 기다리는 비용에 가까움
- dedup은 암호화와 압축 이후 블록 단위로 수행됨
- 같은 원본 데이터라도 압축 방식, 암호화 키, 파일 내 정렬까지 맞아야 같은 블록으로 취급됨
- 일반 목적 워크로드에서는 “진짜로 같은” 블록이 적어 dedup 비용이 이득을 넘기기 쉬움
Fast Dedup의 개선점
-
live entry 축소
- Fast Dedup은 먼저 live entry list의 메모리 footprint를 줄임
ddt_entry_t의 큰 숫자 타입 플래그를 bitfield로 바꾸고, 동기화 필드를 단순화함- dedup된 데이터 블록을 처음 쓰거나 repair write가 필요할 때만 쓰는 40바이트 상태를 별도 IO state 객체로 분리함
- 기존 dedup entry 값은 네 개의 physical entry를 포함해 256바이트였음
- 각 physical entry에는 세 개의 128비트 DVA, refcount, birth transaction id가 들어감
- 네 번째 entry는 과거
dedupditto기능의 흔적이며, 현대 OpenZFS는 읽기만 지원하고 새로 쓰지 않음 - Fast Dedup은
copies=가 바뀌어 더 많은 DVA가 필요할 때 기존 variant를 별도 entry처럼 유지하지 않고, 필요한 추가 복사본만 할당해 기존 dedup entry에 더함 - 새 Fast Dedup table의 entry 값은 기존 256바이트에서 72바이트로 줄어듦
- live list의 entry 하나는 기존 424바이트에서 216바이트로 감소함
-
dedup log 도입
- 기존 방식은 트랜잭션 종료 때 live entry list를 dedup ZAP에 바로 반영했고, entry 주변 187개 항목이 대부분 무관한 상황에서도 블록 단위 갱신 비용이 발생함
- Fast Dedup은 최근 생성·중복된 블록이 다시 중복되거나 해제될 가능성이 더 높다는 관찰을 바탕으로 dedup log를 추가함
- 트랜잭션 끝에 live entry 변경을 ZAP에 바로 쓰지 않고 로그에 기록함
- on-disk log는 crash safety를 위해 필요함
- in-memory log는 빠른 lookup을 위해 유지됨
- lookup 순서는 live entry list, in-memory log, dedup ZAP 순서가 됨
- on-disk log는 pool import 시 in-memory log를 복원하는 데 사용됨
-
점진적 log flush
- 초기 방식처럼 로그가 너무 커졌을 때 한 번에 ZAP으로 flush하면 수천 entry만으로도 긴 pause가 생길 수 있었음
- Fast Dedup은 매 트랜잭션마다 로그 일부를 ZAP에 반영하는 incremental flushing을 사용함
- flush 양은 실제 IO에 소비한 시간과 비교해 조절됨
- 바쁜 시기에는 덜 쓰고, 조용한 시기에는 더 씀
- in-memory log가 커져 메모리 압박을 만들면 flush를 가속할 수 있음
- on-disk log를 append-only로 유지하면서도 전체 중단 없이 비우기 위해 두 개의 log를 사용함
- 하나는 active log로 새 변경을 받음
- 다른 하나는 flushing log로 ZAP에 반영됨
- flushing log가 비면 on-disk log를 zero 처리하고 두 log의 역할을 바꿈
- scrub이나 resilver 같은 pool scan에서는 dedup log에 안정적인 위치 개념이 없기 때문에, scan 요청 시 log flushing을 가속해 dedup ZAP에 모두 반영한 뒤 기존 방식으로 scan함
unique entry 관리와 운영 기능
zpool ddtprune은 pool의 dedup table에서 일부 unique entry를 제거함- age 또는 percentage 기준으로 지정할 수 있음
- age 기준은 최근 사용 데이터가 다시 중복될 가능성이 높은 워크로드에 특히 잘 맞음
- pruning으로 dedup entry가 제거된 블록이 나중에 복사되면 기존 블록과 중복 제거되지 않고 새 블록으로 할당됨
- 다만 오래된 unique block이 갑자기 여러 번 복사되면 새 블록 하나에 대한 여러 참조가 생길 수 있음
dedup_table_quotapool property는 dedup table의 최대 크기를 제한함- 새 entry 생성이 한도를 넘기면 entry를 만들지 않고 일반 non-dedup write로 처리함
- dedicated dedup device가 가득 찼을 때 main device로 넘치지 않게 하는 용도로 함께 쓸 수 있음
zpool prefetch -t ddt는 dedup table을 ARC에 미리 올림- pool import 직후 성능에 도움이 될 수 있음
- Fast Dedup에서도 log에 없는 entry 조회와 flush 시 ZAP 접근이 필요하므로 유효함
- 새 kstats와 tuneable도 추가됨
- Linux:
/proc/spl/kstat/zfs/<pool>/ddt_stats_<checksum> - FreeBSD:
kstat.zfs.<pool>.misc.ddt_stats_<checksum> - Linux tuneable:
/sys/modules/zfs/parameters/zfs_dedup_log_* - FreeBSD tuneable:
vfs.zfs.dedup.log_*
- Linux:
zpool status -D,zdb -D,zdb -S같은 기존 dedup-aware 도구도 새 구조를 이해하도록 갱신됨
기존 dedup table과의 호환성
- Fast Dedup의 대부분은 on-disk format 변경이 필요하므로 기존 dedup table에는 그대로 적용되지 않음
- 기존 table에서도 온디스크 형식 변경이 필요 없는 기능은 동작할 수 있음
dedup_table_quotazpool prefetch -t ddtddt_stats_*lookup 및 hit count- ZAP shrink
- dedup log를 전통적 table에서도 작동하게 만드는 일은 비교적 straightforward한 작업으로 남아 있음
- 다만 더 작은 live/log entry의 이점은 얻지 못함
zpool ddtprune은 기존 table에서 “percentage of uniques” 모드만 추가하기 쉬움- age 모드는 새 entry format의 데이터가 필요해 기존 format에서는 불가능함
- 기존 table을 새 format으로 변환하는 기능은 현재 없음
copies=가 바뀐 적 없는 단순한 경우에는 새 ZAP을 만들고 기존 entry를 변환·복사하는 방식이 가능함- online 변환은 old/new ZAP 동시 조회나 동시 쓰기가 필요해 복잡함
- offline 변환은 더 쉽지만 pool을 offline으로 내려야 함
copies=변경으로 여러 variant가 refcount를 가진 경우 완전 변환이 불가능할 수 있음
- deduplicated dataset을 새 dedup이 가능한 다른 pool로 보내는 방식은 동작함
“좋아졌지만 왜 켜지 말아야 하나”
- Fast Dedup은 기존보다 overhead가 줄어 더 많은 marginal 상황에서 유용할 수 있음
- 하지만 dedup은 여전히 IO 처리량, 메모리 사용량, dedup table 크기 사이의 균형 문제임
- 일반 목적 workload에서는 중복 가능한 블록이 매우 드물 수 있음
- 예시 laptop pool의
zdb -Ssimulated DDT 결과는 dedup 이득이 거의 없었음- 11.7M entry 대부분이 refcount 1인 unique entry였음
- 실제 dedup 가능한 entry 수는 전체에서 반올림 오차 수준이었음
dedup = 1.00으로 나타남
- 이런 경우 dedup을 켜면 거의 얻는 것 없이 IO와 메모리 압박만 추가됨
BRT/block cloning이 더 나은 경우
- OpenZFS 2.2부터는 BRT, 즉 block cloning 또는 reflinks가 있음
- dedup table은 “이 데이터가 이미 디스크에 있는가”를 문맥 없이 알아내기 위한 구조임
- 현대 시스템에서는 복사 작업이 복사임을 storage stack에 전달할 수 있는 경우가 있음
- Linux와 FreeBSD 파일시스템의
copy_file_range() - macOS의
copyfile() - Windows의
FSCTL_SRV_COPYCHUNK - NFS, CIFS, OS block device driver, SCSI EXTENDED COPY, NVMe Copy 등에도 유사 기능이 있음
- Linux와 FreeBSD 파일시스템의
- 클라이언트 프로그램과 중간 계층이 copy offload 신호를 전달하면 OpenZFS는 BRT에서 refcount만 늘릴 수 있음
- BRT는 블록이 clone되지 않으면 비용을 내지 않고, clone된 경우 entry가 16바이트임
- 예시 pool에서 BRT는
used 292M; saved 309M; ratio 2.05x를 보였음 - dedup simulation보다 raw saving이 조금 적고 비슷한 수준이지만, clone되지 않은 블록 전체를 추적하는 큰 비용은 없음
실무적 판단 기준
- Fast Dedup은 전통적 dedup의 세 축인 IO throughput, memory usage, dedup table size를 모두 개선함
- 실패 시 재앙적 비용도 줄었고, 운영자가 table을 제한·정리할 도구도 생김
- 그래도 이득을 보려면 조건이 분명함
- 데이터 규모가 매우 커야 함
- 같은 데이터가 많이 복사되어야 함
- block cloning이나 snapshot clone 같은 OpenZFS의 다른 zero-copy 선택지를 쓸 수 없어야 함
- 클라이언트가 “복사해 달라”는 명확한 신호를 줄 수 있는 워크로드라면 block cloning이 더 낮은 비용으로 큰 이득을 제공할 수 있음
댓글과 토론
Hacker News 의견들
-
오프라인 중복 제거나, 풀을 완전히 내리지 않아도 되지만 즉시 실행되지는 않는 지연 중복 제거가 있으면 좋겠음
중복 제거를 켜면 모든 쓰기와 해제 작업마다 중복 제거 테이블 조회와 쓰기가 필요하다는 점이 대부분의 경우 잘못된 접근처럼 보임. 데이터를 쓸 때는 디스크 공간을 더 쓰더라도 최대한 빨리 끝나길 원하고, 그래서 작업 중인 파일을 7zip 아카이브 안에 저장하지 않는 것임. 나중에 시스템이 한가할 때 ZFS가 중복 데이터를 찾아 BRT 같은 것으로 공간을 회수하면 좋겠고, 일반적인 스크럽 작업의 일부로 할 수도 있어 보임- 지연/오프라인 중복 제거에는 블록 포인터 재작성이 필요한데, ZFS는 진짜 CAS 시스템이 아니라서 앞으로도 제대로 된 BP 재작성을 얻기 어려움
물리 위치가 Merkle 해시 트리에 해시되어 들어가므로 물리 위치를 옮기려면 바꾸려는 노드까지 가는 내부 노드들을 모두 다시 써야 해서 비용이 너무 큼. 더 나은 설계는 블록 포인터가 있는 모든 노드를 논리 블록 포인터만 있고 트리에 해시되는 부분과, 그 논리 포인터에 대응하는 물리 위치만 캐시처럼 담되 Merkle 트리에는 해시하지 않는 부분으로 나누는 것이었을 것임. 그러면 BP 재작성은 Merkle 트리에 속하지 않는 블록만 다시 쓰면 됨. 지금 구조에서는 원하는 기능을 ZFS에서 얻기 어렵지만, 읽기 때 해시 불일치가 나면 포인터의 해시로 중복 제거 테이블에서 블록을 찾고 중복 제거된 블록을 재할당하는 식의 우회는 가능할지도 모름. 그 대가는 쓸모없는 읽기 한 번 정도라 아주 나쁘진 않지만, BP 재작성이 불가능하면 보통 이런 땜질이 생김 - 이 방식은 Windows 중복 제거 방법론과 같음. 꽤 많이 써 봤고, 하드웨어가 충분하면 대체로 만족스러웠음
RAM과 입출력을 많이 먹지만 “groveler”를 예약하고 제한할 수 있음. 다만 Windows 2012 R2 시절 버그 때문에 데이터를 먹는 손상을 겪은 적이 있음 - 이건 오프라인 중복 파일 탐지기로도 가능함
예를 들면 jdupes나 duperemove가 있음. 필요한 시스템 호출을 지원하도록 ZFS 쪽과 duperemove 쪽에 PR을 보냈음. ZFS 쪽은 리뷰가 오래 걸렸고 마무리를 완전히 잊고 있었다는 걸 깨달아서 다시 챙겨야 함 - ZFS에서 기존 스냅샷을 바꾸는 능력은, 데이터가 완전히 보존되는 방식이라도 극히 제한적임. 그래서 그런 기능이 있으면 좋겠지만 Block Pointer Rewrite를 기다리고 있었다면 이미 오래전에 죽었을 것임
- 인라인 중복 제거의 좋은 점은 블록 해시가 이미 있으면 그 블록을 실제로 쓰지 않아도 된다는 것임
여러 상황에서 쓰기 입출력을 크게 줄일 수 있음. 중복 제거 스토리지 배열에서 두 VM 사이에 파일 복사를 하면 실제 데이터는 복사하지 않고 원래 블록의 참조 카운터만 올리는 확장도 있음. 운영체제에서는 터무니없는 TB/s 쓰기 속도로 보이는데 꽤 멋짐
- 지연/오프라인 중복 제거에는 블록 포인터 재작성이 필요한데, ZFS는 진짜 CAS 시스템이 아니라서 앞으로도 제대로 된 BP 재작성을 얻기 어려움
-
“전통적인 중복 제거의 근본 문제는 이런 오버헤드가 너무 커서 드물고 특정한 작업부하가 아니면 회수하기 어렵다”는 주장은 꽤 이상하게 들림
Pure와 Dell/EMC 배열을 다뤄 봤고, VMWare 작업부하에서는 보통 중복 제거/압축으로 최소 3:1 절감이 나왔음. 기본 VM 이미지 사본을 하나만 저장하는 방식은 매우 잘 동작함. syslog 서버에서도 중복 제거/압축이 잘 먹혀서 6:1 절감을 본 적이 있음. 중복 제거 효과는 해시되는 블록 크기에 크게 좌우되고, 작을수록 좋음. 블록이 작아질수록 일치하는 블록이 생길 확률이 빠르게 커지며, 경험상 선호하는 블록 크기는 4KB임- VM 이미지는 Windows Server 이미지들의 C 드라이브가 거의 같듯이 중복성이 매우 높은 정보이고, 원문은 자기 노트북 내용을 예로 들었음
또 압축과 중복 제거라는 서로 다른 기능을 섞고 있는 듯함. ZFS에서는 풀에 압축을 켤 수 있고 거의 항상 가치가 있지만, 중복 제거는 꺼둘 수 있음 - 기본 VM 이미지는 드물고 특정한 작업부하에 해당하며, 중복 제거가 말이 되는 몇 안 되는 경우임
다만 ZFS 파일시스템 위에서 VM을 호스팅한다면 블록 또는 파일시스템 클론 같은 더 나은 전략을 쓰고 있을 가능성이 큼. 그러지 않는 건 그 환경에서 ZFS의 핵심 차별점 하나를 버리는 셈임. 범용 파일 서버나 개인 데스크톱/노트북 사용에서는 보통 중복 블록이 매우 적어서 오버헤드가 아깝다. 백업은 구현 방식과 파일시스템 계층 전에 암호화되는지에 따라 될 수도 있고 아닐 수도 있음. 압축은 완전히 다른 이야기고, 현재 ZFS 모범 사례는 거의 모든 작업부하에서 기본으로 켜는 것임. 요즘은 CPU 비용이 언급할 가치도 작고, 저장 공간 절감과 별개로 입출력 절감이 상당할 수 있음. 일반적인 로그 저장소라면 경험상 6:1보다 훨씬 좋은 절감도 가능함 - 직접 해보진 않았지만, 예전 ZFS 중복 제거에 대해 널리 인용되는 수치는 디스크 1TB당 RAM 5GB가 필요하다는 것임
현재 디스크 1TB가 약 15달러, 서버 RAM 5GB가 약 25달러라고 보면 손익분기만 맞추려 해도 3:1 중복 제거율이 필요함. 데이터가 잘 맞으면 TB당 1GB로도 버틸 수 있겠지만, 운이 나쁘면 5GB도 충분하지 않을 수 있음. 그래서 글에서 ZFS 중복 제거는 데이터가 딱 맞아야 하는 작은 sweet spot이 있다고 한 것이고, 대부분이 신경 쓰지 않는 이유임. 다른 파일시스템들은 보통 경제성이 더 나은 오프라인 중복 제거를 선호함 - VM은 중복 제거의 이점이 알려져 있으니 그쪽에서는 효과를 볼 수 있음. 하지만 ZFS는 기업용 SAN만이 아니라 범용 파일시스템이라 많은 ZFS 사용자가 VM을 돌리는 것은 아님
syslog에서 중복 제거/압축이 잘 된다는 표현은 세부적으로 보면 중복 제거와 압축은 같은 것이 아님. 기업용 스토리지 세계에서는 둘이 묶이는 경우가 많지만, 로그는 아마 중복 제거가 아니라 압축의 이점을 보는 것이고 ZFS에는 원래부터 압축이 있었음 - VM 기본 이미지를 깊은 복사로 여러 개 두지 않는 건 당연히 말이 되지만, ZFS에서는 중복 제거가 적절한 방법은 아님
대신 기본 이미지를 클론하면 변경 전에는 공간을 거의 차지하지 않음. 이는 ZFS의 쓰기 시 복사 특성 덕분임. ZFS 중복 제거는 볼륨에 쓰이는 데이터의 기존 사본을 찾으려는 기능임. 컨테이너 이미지 저장소 같은 일부 용도에는 꽤 말이 될 수 있지만, 어떤 데이터셋이 처음부터 다른 것의 클론이라는 걸 이미 알고 있다면 매우 비효율적임
- VM 이미지는 Windows Server 이미지들의 C 드라이브가 거의 같듯이 중복성이 매우 높은 정보이고, 원문은 자기 노트북 내용을 예로 들었음
-
예전에는 ZFS 중복 제거를 광범위하게 썼고 큰 이득을 봤음. 구체적인 용도는 VMWare 클러스터용 스토리지였고, 내용이 대체로 같은 Linux와 Windows VM 수백 대가 있었음. Docker 이전 시절 이야기임
- 여기서 VM에 중복 제거를 쓴 사례가 여러 개 보이는데, 이건 파일시스템보다 하이퍼바이저에서 구현하는 편이 훨씬 효율적이지 않을까 싶음
- 공감됨. 최근 Ubuntu의 “experimental” zfs가 들어간 새 업무용 노트북을 받았는데, nix store에 중복 제거를 쓰는 게 정말 큰 도움이 됐음
-
빠른 중복 제거가 너무 기대됨. 몇 년 동안 ArchiveBox 데이터에 ZFS 중복 제거를 쓰고 싶었는데, 빠른 중복 제거 덕분에 수백만 URL을 한 컬렉션에 아카이브하고 파일시스템이 전체 압축을 맡는 방식이 드디어 가능해질 것 같음
아카이브 데이터에는 jquery.min.js, bootstrap.min.css, 로고 이미지 같은 것이 수천 개 스냅샷에 반복해서 들어감. 다른 도구들은 한 번의 크롤 안에서 압축해 wacz나 warc.gz 파일을 만들지만, 어떤 도구도 지금까지 찍은 모든 스냅샷의 전체 데이터베이스를 가로지르는 압축을 시도한 것 같지는 않음. 혹시 전체 중복 제거 해시 테이블을 그대로 저장하지 않도록 Bloom filter 같은 것을 쓰는 확률적 중복 제거 접근을 시도해 본 사람이 있는지도 궁금함. 블록 해시 약 100개씩을 버킷으로 묶고, Bloom filter에 초압축 표현을 저장함. 쓰기 때 쓸 블록의 해시를 Bloom filter에서 조회하고, 잠재적 중복 제거 적중이 감지되면 해당 버킷의 100개 블록을 직접 훑어 동일 해시를 찾는 식임. 이론적으로는 해상도가 다른 Bloom filter 계층을 두고, 메모리 압박이 높을 때 고해상도 필터를 디스크로 동적으로 내릴 수도 있음. Bloom filter 정확도를 조정 가능한 매개변수로 두면 CPU 시간/오버헤드와 절약 바이트 비율에 대한 선호를 고를 수 있음- 이 변경이 있어도 ZFS 중복 제거는 여전히 블록 정렬 기반이라, 반복되는 웹 자산이 WARC 아카이브 안에서 항상 같은 오프셋에 있지 않으면 잘 맞지 않을 것임
dm-vdo도 같은 동작을 함. 대신 긴 범위를 보는 solid 압축을 쓰거나, WARC 파일을 디렉터리 형태에 준하는 구조로 풀거나, 콘텐츠 정의 청킹 기반 FUSE 시스템이 있다면 그쪽이 나을 수 있음. Seafile이 그럴지도 모름 - 용도는 이해하지만, 대부분의 경우 특히 이 경우에는 클라이언트 쪽에서 구현하는 편이 훨씬 나을 것 같음
WARC 표준을 보면 이미 해시 기반 중복 제거를 하고, 처음 저장한 뒤에는 포인터를 쓰는 방식이 있음. 그래서 파일시스템 계층 중복 제거가 그다지 좋지 않은 정확한 사례임 - 용도는 조금 다르지만, zbackup을 모른다면 좋아할 것 같음
- 이 변경이 있어도 ZFS 중복 제거는 여전히 블록 정렬 기반이라, 반복되는 웹 자산이 WARC 아카이브 안에서 항상 같은 오프셋에 있지 않으면 잘 맞지 않을 것임
-
RAM 사용량을 줄인 상태에서 이걸 제대로 동작시키는 데 왜 그렇게 어려움을 겪는지 궁금함. 상용 스토리지 어플라이언스들은 붙은 디스크 용량에 비해 RAM이 “적은” 시스템에서도 적어도 10년쯤 전부터 해내고 있었음
그냥 지문을 데이터베이스에 저장하고 밤에 훑으면서 블록 포인터를 고치면 되지 않나 싶음- “블록 포인터를 고친다”가 바로 이유임. 여러 이유로 ZFS에는 블록 포인터 재작성 능력이 없음
오래 요청된 기능이고, 가능해지면 조각 모음도 할 수 있음. 가상 메모리처럼 블록 포인터 간접화를 쓰면 약간의 속도 비용으로 해결할 수 있지 않을까 생각해 봤지만, ZFS 개발자가 아니라 분명 놓치는 게 있을 것임. http://eworldproblems.mbaynton.com/posts/2014/zfs-block-poin... / https://github.com/openzfs/zfs/issues/3582 - 블록 포인터를 고치는 것이야말로 ZFS가 하지 않으려던 한 가지임
- DragonFlyBSD와 Hammer2를 쓰는 방법도 있음. Hammer2는 온라인과 오프라인 중복 제거를 모두 지원하고 여러 면에서 ZFS와 매우 비슷함
큰 단점은 RDMA를 쓰는 파일 전송 프로토콜이 없다는 점임. Hammer2를 FreeBSD에서 돌릴 수 있게 하는 실험 브랜치도 있다고 들었음. 하지만 FreeBSD도 RDMA 지원이 없음. FreeBSD 15에서는 Chelsio가 NVMe-oF 대상과 개시자 지원을 후원했는데, TCP만 해당하는 것 같음
- “블록 포인터를 고친다”가 바로 이유임. 여러 이유로 ZFS에는 블록 포인터 재작성 능력이 없음
-
cp --reflink=auto를 쓰면 됨
파일 수준 중복 제거를 얻을 수 있음. 이 명령은 가벼운 복사를 수행하며, 파일 수준의 ZFS 클론처럼 데이터 블록은 수정될 때만 복사됨. 하드 링크가 아니라 복사본임. reflink를 지원하는 다른 쓰기 시 복사 트랜잭션 파일시스템에서도 같은 방식이 동작할 것임 -
ZFS를 정말 쓰고 싶었지만, 모든 데이터는 당연히 암호화되어야 함. 그런데 사용법이 예상보다 훨씬 복잡해지고, 일이 꼬이니 많은 사람이 그냥 데이터를 암호화하지 않는다는 점이 놀라웠음
Proxmox조차 웹사이트에 “Enterprise”가 붙어 있어 기본 설치에서 암호화를 지원할 줄 알았는데, 암호화와 함께 쓰려 하면 중요한 기능을 잃음. 이슈 트래커도 꼭 살펴봐야 함. 운영 파일시스템에 있을 거라고는 예상 못 한 놀라운 것들이 몇 가지 있음- ZFS를 암호화하는 가장 좋은 방법은 암호화된 볼륨, 예를 들면 LUKS 볼륨 위에 암호화하지 않은 ZFS를 올리는 것임. ZFS “암호화”는 평문으로 남기는 것이 너무 많아서 불안함
-
파일시스템으로서 완전히 다른 API가 있었으면 좋겠음. 모든 운영체제의 파일시스템 API 표면은 하위 호환성 때문에 갇혀 있는 완전한 난장판임
- 내부적으로 ZFS는 본질적으로 객체 저장소임. 이를 객체 저장소 API로 노출하려는 작업이 있었지만, 안타깝게도 어디로도 이어지지 않은 것 같음
발표를 찾아보려 했지만 실패했음. Developer Summit에서 본 줄 알았는데 아니었나 봄 - 왜 난장판이고 무엇으로 대체할 수 있을까? AWS S3식 API가 개선일까?
- 내부적으로 ZFS는 본질적으로 객체 저장소임. 이를 객체 저장소 API로 노출하려는 작업이 있었지만, 안타깝게도 어디로도 이어지지 않은 것 같음
-
중복 제거는 잊고 ZFS 압축을 쓰는 편이 훨씬 가성비가 좋음
- 데이터셋이 이미 강하게 압축된 미디어 파일이라면 예외임
일반적으로 rsync 작업 중에도 큰 동영상 파일에는 압축을 끄곤 함. 압축이 저장공간이나 전송에는 효과가 낮거나 오히려 없는데 RAM과 CPU를 먹기 때문임. 중복 제거는 Virtual Machine OS 이미지에 좋음. 저장 비용 대부분이 반복된 기반 이미지이기 때문임
- 데이터셋이 이미 강하게 압축된 미디어 파일이라면 예외임
-
범용 중복 제거는 이론상 좋아 보이지만 실제로는 잘 안 풀리는 경우가 많음. IPFS는 rsync처럼 데이터를 중복 제거하려고 가변 크기 조각과 롤링 해시를 쓰지만, 실제로는 차이를 만들지 못하고 괜히 복잡성만 더함