LabHub
배우기 러닝패스 코스

Apache Hadoop — 1つのPodにHDFSとYARNを立てて運用する

小さなファイル 2,000 個をアーカイブにまとめ、NameNode のオブジェクト数を測る

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

센서 CSV 2,000개(파일 하나에 수백 바이트)를 HDFS 에 올려 NameNode 가 들고 있어야 하는 객체(파일·디렉터리·블록)가 몇 개인지 재고, 하둡 아카이브(HAR)로 묶어 그 수가 얼마나 주는지 본다. 묶은 뒤에도 har:// 로 원래 파일을 하나하나 읽을 수 있는 것과, distcp 로 아카이브를 통째로 옮기는 것까지 해 본다.

왜 중요한가

NameNode 는 파일·디렉터리·블록 하나하나를 자바 객체로 힙에 들고 있다. 파일이 1바이트든 1GB 든 객체 수는 같다. 그래서 HDFS 의 한계는 대개 디스크가 아니라 NameNode 의 힙이고, 수백만 개의 작은 파일은 디스크를 거의 쓰지 않으면서 NameNode 를 먼저 쓰러뜨린다. 맵리듀스·Spark 입장에서도 작은 파일은 파일마다 태스크나 열기 비용이 붙어 느리다. 해법은 파일을 덜 만드는 것이다 — 쓸 때 모아서 쓰거나(Spark 의 repartition·coalesce, 큰 컨테이너 파일 형식), 이미 생긴 것을 묶는다. HAR 은 뒤쪽 방법이다. 많은 파일을 큰 파일 몇 개(part-*)와 색인(_index·_masterindex)으로 바꿔 NameNode 의 객체 수를 줄이고, 읽을 때는 har:// 파일 시스템이 색인을 보고 원래 경로로 찾아 준다. 대신 한 번 만든 아카이브는 고칠 수 없다(읽기 전용). 이 실습은 아카이브와 distcp 를 YARN 없이 로컬 실행기로 돌린다. 둘 다 맵리듀스 잡이지만 실행 위치는 설정 하나로 바뀐다 — 같은 잡이 노트북에서도 클러스터에서도 돈다.

단계

  1. /data/small 디렉터리(파일 2,000개)를 HDFS /user/root/small/raw 로 올리세요(hdfs dfs -put -t 8 로 여러 줄기로 올리면 빠릅니다).
  2. raw 의 파일 수·디렉터리 수·블록 수를 /root/hdp/small/objects.json{"raw_files": 정수, "raw_dirs": 정수, "raw_blocks": 정수} 로 쓰세요.
  3. hadoop archive -D mapreduce.framework.name=local -archiveName raw.har -p /user/root/small -r 1 raw /user/root/small/archive 로 아카이브를 만드세요.
  4. hdfs dfs -ls -R har:///user/root/small/archive/raw.har 로 아카이브 안의 파일 수를 세어 /root/hdp/small/har_files.txt 에 정수로 적으세요.
  5. har:// 경로로 raw/sensor-0042.csv 를 읽어 로컬 /root/hdp/small/sensor-0042.csv 에 저장하세요.
  6. raw 와 raw.har 의 NameNode 객체 수(파일 + 디렉터리 + 블록)를 /root/hdp/small/compare.json{"raw_objects": 정수, "har_objects": 정수} 로 쓰세요.
  7. hadoop distcp -D mapreduce.framework.name=local /user/root/small/archive /user/root/backup/small-archive 로 아카이브를 복사하세요.
  8. /root/hdp/small/report.md## NameNode 가 치르는 값 ## HAR ## 옮기기 세 절을 쓰세요. 첫 절에 6단계의 raw_objects 를, 둘째 절에 har_objects 를 넣으세요.

참고

작은 파일 2,000개 올리기

/data/small 을 HDFS /user/root/small/raw 로 올리세요. hdfs dfs -put -t 8 /data/small /user/root/small/raw 처럼 여러 줄기로 올리면 빠릅니다.

한 줄기로 올리면 파일마다 NameNode 와 몇 번씩 주고받아서 2,000개에 10분이 넘게 걸립니다. 작은 파일은 크기가 아니라 개수로 비용을 치릅니다 — 이것부터가 작은 파일 문제입니다.

NameNode 가 들고 있는 객체 세기

hdfs dfs -counthdfs fsck/user/root/small/raw 의 파일 수·디렉터리 수·블록 수를 구해 /root/hdp/small/objects.json{"raw_files": 정수, "raw_dirs": 정수, "raw_blocks": 정수} 로 쓰세요.

파일 하나에 블록 하나(파일이 블록 크기보다 작으니까), 거기에 디렉터리 하나. NameNode 힙에서는 이 셋이 모두 객체입니다. 블록 크기가 128MB 여도 수백 바이트짜리 파일의 블록이 128MB 를 차지하지는 않지만, 객체는 똑같이 하나를 차지합니다.

아카이브로 묶기

hadoop archive -D mapreduce.framework.name=local -archiveName raw.har -p /user/root/small -r 1 raw /user/root/small/archive/user/root/small/archive/raw.har 를 만드세요.

아카이브는 맵리듀스 잡입니다. 입력 파일 목록을 나눠 내용을 part-* 로 이어 붙이고, 파일마다 어디에 들어갔는지를 _index 에 적습니다. -D mapreduce.framework.name=local 은 YARN 없이 지금 JVM 안에서 돌리라는 뜻입니다. 원본(raw)은 그대로 남습니다.

har:// 로 안을 보기

hdfs dfs -ls -R har:///user/root/small/archive/raw.har 출력에서 파일(권한이 - 로 시작하는 줄)의 수를 세어 /root/hdp/small/har_files.txt 에 정수로 적으세요.

har:// 파일 시스템은 _index 를 읽어 원래의 디렉터리 트리를 보여 줍니다. NameNode 는 이 2,000개를 모릅니다 — 아카이브 안의 파일은 NameNode 의 객체가 아니라 색인의 줄입니다.

아카이브 안의 파일 하나 읽기

hdfs dfs -cat har:///user/root/small/archive/raw.har/raw/sensor-0042.csv 로 읽은 내용을 로컬 /root/hdp/small/sensor-0042.csv 에 저장하세요.

경로는 har://<아카이브 경로>/<-p 기준 상대 경로> 입니다. har 파일 시스템은 _masterindex·_index 로 part 파일 안의 위치를 찾아 그 바이트만 읽습니다. 원본 /data/small/sensor-0042.csvcmp 로 견줘 보세요.

객체 수를 견주기

raw 와 raw.har 각각의 NameNode 객체 수(파일 수 + 디렉터리 수 + 블록 수)를 구해 /root/hdp/small/compare.json{"raw_objects": 정수, "har_objects": 정수} 로 쓰세요.

raw 는 파일 2,000 + 디렉터리 1 + 블록 2,000 입니다. raw.har 는 디렉터리 하나와 파일 몇 개(_index·_masterindex·part-0·_SUCCESS)와 그 블록뿐입니다. 몇 분의 일로 줄었는지 계산해 보세요.

distcp 로 통째로 옮기기

hadoop distcp -D mapreduce.framework.name=local /user/root/small/archive /user/root/backup/small-archive 로 아카이브를 복사하세요. 복사본의 raw.har 안 파일들이 원본과 같은 길이여야 합니다.

distcp 는 파일 목록을 나눠 여러 맵이 병렬로 복사하는 맵리듀스 잡입니다. 클러스터 사이 이전·백업에 쓰는 표준 도구이고, 작은 파일을 묶어 두면 복사할 파일 수가 줄어 이것도 빨라집니다. 대상 경로가 없으면 원본 디렉터리의 내용이 그 이름으로 복사됩니다.

작은 파일의 값을 숫자로

/root/hdp/small/report.md## NameNode 가 치르는 값 ## HAR ## 옮기기 세 절을 쓰세요. 첫 절에 6단계의 raw_objects 를, 둘째 절에 har_objects 를 숫자로 넣으세요.

NameNode 힙이 무엇을 세는지, HAR 이 무엇을 줄이고 무엇을 포기하는지(읽기 전용), 작은 파일이 애초에 생기지 않게 하려면 쓰는 쪽에서 무엇을 해야 하는지를 적으세요.