하둡에서 InputSplit과 HDFS 블록 사이의 관계

예를 들어 hadoop의 TextInputFormat 을 보자. 이 포맷은 하둡의 default input format인데, 파일에서 text들을 라인 단위로 읽어서 map task에게 제공해주는 역할을 한다. (참고로 key는 파일 내에서 각 라인의 시작 지점까지의 바이트 오프셋 값이다.)

여기서 당연히 한 가지 의문이 생기는데, 기본적으로 InputSplit은 HDFS의 블록으로 쪼개진다. (특별히 따로 InputSplit을 정의하지 않았다면) 그럼 HDFS block boundary가 TextInputFormat의 line boundary와 정확히 일치하지 않을 텐데, hadoop에서는 이를 어떻게 처리하고 있을까?

Hadoop: The Definite Guide 책을 보면, 아래와 같은 그림이 나온다.

그리고 설명하기를, block boundary와 input split의 논리적인 단위 (여기서는 line 단위)가 일치하지 않더라도, input split을 잘 계산하여 처리한다고 나와 있다. 이 설명만 놓고 보면, 마치 InputFormat에서 InputSplit을 계산할 때, 이런 논리적인 단위가 나눠지는 것처럼 보인다.

하지만 실제로 InputSplit을 구현한 FileSplit을 코드를 보면, 아래와 같은 정보만을 가지고 있다.

  • private Path file;   // 어떤 file에서 나온 split인가
  • private long start; // file 내에서 해당 input split의 시작 위치
  • private long length;  // input split의 크기
  • private String[] hosts; //  해당 input split을 가지고 있는 data node들의 host name

그리고 이런 FileSplit을 계산해 내는 FileInputFormat 클래스 소스를 살펴보면, 논리적인 단위를 계산하는 부분은 없고, 단지 file을 block boundary 단위로 나누어, FileSplit을 계산한다. 즉, FileSplit이 가지고 있는 정보는, 논리적인 단위가 아닌, 단순히 물리적인 block의 경계에 대한 정보만 가지고 있다. 그렇다면 실제로 block 단위가 아닌, line 단위로 input split을 재계산 해 주는 녀석은 누구일까?

비밀은 바로 RecordReader에 숨어 있다. InputFormat interface는 getSplits() 메소드를 통해 split을 계산해내고, getRecordReader() 메소드를 통해 해당 split을 읽을 수 있는 RecordReader를 반환한다.

그리고 각 MapTask가 실행될 때, map() 메소드를 호출하기 전에 RecordReader의 initialize() 메소드를 한 번 호출한다. 그리고 TextInputFormat이 사용하는 LineRecordReader의 initilize() 메소드를 살펴보면, map task로 전달된 input split이 파일의 첫 번째 block이 아닐 경우, 무조건 첫 번째 line은 skip하도록 구현되어 있다. (start position에 -1을 한 다음, 한 줄을 건너뜀) 이제 저 위 그림이 이해가 될 것이다.

정리를 하면, file을 처리하는 InputSplit은 단순히 물리적인 block 단위 (기본적으로는 hdfs block 단위)로 쪼개져서 map task에게 전달된다. 그리고 각 map task는 이렇게 쪼개진 input split으로부터, 실제로 map() 에서 처리해야 하는 논리적인 record 단위를 계산하고, 이를 바탕으로 InputSplit의 boundary를 다시 계산하여 처리를 하게 되는 것이다.

댓글(6)

  • 2011.08.09 22:33 신고

    저것땜에 고생한걸 생각하면 ㅠㅠㅠㅠㅠㅠㅠㅠ 하나 덧붙이자면 마지막 글자가 뉴라인이 아니면 다음 블락의 일부분을 조금더 보내서 newline이 나오는 순간 끝내게 되죠. ㅠㅠ

    • 2011.08.20 01:25 신고

      ㅋㅋ 다들 삽질하는 게 비슷하구나. 그나저나 kaje는 요즘 뭘 하길래, hadoop 때문에 고생해? ㅎㅎ 대학원? 회사? 다른 곳에서도 hadoop을 많이 쓰나~~?

  • 2012.07.02 20:18 신고

    아 지금 저거떄문에 머리가 아파요 .................................... 모좀 짜르고 싶은데 짜르는게 문제네요 ..

  • 2020.08.17 17:37 신고

    You saved my day 많은 도움이 되었습니다 ^^ 감사합니다!
    이해가 안 가는 것이 있는데요, 예제 그림의 5번이나 9번을 보면 boundary 때문에 데이터가 중간에 잘렸음에도 불구하고 split 은 5와 9 데이터를 line 단위로 가져오잖아요
    이게 대해 설명해주는 것이 "첫번째 block 이 아니면 skip 한다" 인데 이게 이해가 잘 안 가요. 첫번째 block 이라는 게 6번 10번 데이터를 말하는거겠죠? 그것을 skip 하는건 이해가 되는데, 그게 5번 9번 데이터는 라인 단위로 자를 수 있다는 의미는 아닌 것 같아서

    • 2020.08.24 22:38 신고

      첫 번째 block 이라는 건 1~5번째 줄을 포함하는 데이터라고 보시면 됩니다.
      두 번째 block은 물리적으로 보면, 5.5줄~9.5줄인데.. 이렇게 되면, 5번 째 줄을 1번 split에서도 읽게 되고, 2번 split 에서도 읽게 되는 문제가 발생하잖아요? 그러니 아예 block boundary에 걸쳐 있는 줄은 이전 block에서 읽도록 처리하겠다! 이렇게 이해하시면 될 것 같아요.

  • 2020.08.26 09:41 신고

    자세한 답변 감사합니다!

Designed by JB FACTORY