원제 : Google Architecture

번역 : Google Architecture

Update 2: Sorting 1 PB with MapReduce. PB 는 peanut-butter-and-jelly 을 잘못쓴 것이 아닙니다. PB는 1000 TeraByte 또는 백만 기가바이트입니다. 4000대의 컴퓨터 있는 1 PB 정렬하는데 6시간 2분 걸리고 결과는 4만 8천개의 디스크로 복제됩니다.. (10조개의 100 byte 레코드)
Update: Greg LindenMapReduce: simplified data processing on large clusters 라는 새로운 Goolge 문서를 발표했습니다. 몇 가지 흥미로운 통계 : 10만개의 MapReduce 작업이 매일 실행됩니다; 매일 20PB 데이터가 처리됩니다; 십만개 이상의 MapReduce 프로그램이 실행됩니다; 장비들은 기가비트 이더넷과 4-8B 메모리를 가는 듀얼 프로세스입니다.

Google은 확장성의 최고입니다. 모두가 Google을 크고, 세련되고, 빠른 검색으로 알고 있지만, 검색에서는 그렇게 뛰어나지 않습니다. 확장 가능한 응용프로그램을 구축하는 Google의 플랫폼 접근법은 Google이 놀랄 만큼 높은 경쟁에서 인터넷 규모의 응용프로그램을 출시할 수 있게 해줍니다. Google의 목적은 항상 Google 제품을 지원하는 더 높은 성능과 확장가능한 인프라를 구축하는 것입니다. 어떻게 했을까요??

Information Sources

  • Video: Building Large Systems at Google
  • Google Lab: The Google File System
  • Google Lab: MapReduce: Simplified Data Processing on Large Clusters
  • Google Lab: BigTable.
  • Video: BigTable: A Distributed Structured Storage System.
  • Google Lab: The Chubby Lock Service for Loosely-Coupled Distributed Systems.
  • How Google Works by David Carr in Baseline Magazine.
  • Google Lab: Interpreting the Data: Parallel Analysis with Sawzall.
  • Dare Obasonjo's Notes on the scalability conference.

  • Platform

  • Linux
  • 언어의 다양성(A large diversity of languages) : Python, Java, C++

  • 내부를 살펴볼까요?

    통계

  • 2006년도 기준으로 약 45만대 저가 서버 추산
  • 2005년, Google은 약 8십억개 웹페이지를 색인. 현재는 누가 알까요?
  • 현재 Google 에는 200개가 넘은GFS 클러스를 가지고 있습니다. 클러스터는 천에서 5천대의 장비를 가질 수 있습니다. 만대의 장비 풀은 5PB 가 넘는 스토리지에 동작하는 GFS로투터 데이터를 불러옵니다. 읽기/쓰기 합계 처리량은 클러스터 간에 40기가/초보다 높습니다.
  • 현재 Google에서는 6000개가 넘는 MapReduce 응용프로그램이 있으며, 매달 수백개의 새로운 응용프로그램이 작성됩니다.
  • BigTable은 수십억개의 URL, 수백 TB의 위성 사진, 수억명 사용자의 설정을 저장하기 위해 확장됩니다.

  • The Stack

    Google 은 3개의 레이어 스택으로 인프라를 시각화합니다.:

  • 제품 : 검색, 광고, 이메일, 지도, 비디오, 채팅, 블로그
  • 분산 시스템 인프라 : GFS, MapReduce, BigTable.
  • 컴퓨팅 플랫폼 : 다른 데이터센터에 있는 장비 묶음
  • 회사사람들이 낮은 비용으로 배치할 수 있게 용이함을 확신시킵니다.
  • 응용프로그램 단위로 가격 대비 성능데이터를 살펴봅니다. 로그 데이터를 잃지 않기 위해 하드웨어에 돈을 더 투자하지만, 다른 종류의 데이터에는 투자하지 않습니다. Google은 데이터를 잃지 않는다고 말합니다.

  • GFS를 통한 안정적인 저장 메커니즘 (Google File System)

  • 안정적인 확장가능한 저장은 모든 응용프로그램의 핵심 요소입니다. GFS는 Google의 핵심 저장 플랫폼입니다.
  • Google File System - 많은 데이터를 보내는 커다란 분산 로그 구조 파일 시스템( large distributed log structured file system )입니다.
  • 선반 소프트웨어 대신에 왜 구축을 했을까요? 모든 것을 제어하고 싶고 다른 사람들과 Google을 구별해주는 플랫폼이기 때문입니다. Google의 요구사항입니다 :
    - 데이터센터간의 높은 신뢰성
    - 수천개의 네트워크 노드에서 확장성
    - 매우 높은 읽기/쓰기 대역폭 요구사항
    - 크기에서 기가바이트 정도의 큰 데이터 블록의 지원 .
    - 병목을 감소시키기위해 노들간의 동작의 효율적인 분산
  • 시스템은 마스터와 chunk 서버로 구성됩니다.
    - 마스터 서버는 다양한 데이터 파일의 메타데이터를 보관합니다. 데이터는 64MB 조각으로 파일 시스템에 저장합니다. 클라이언트는 마스터 서버에게 파일의 메타데이터 동작을 수행하과 디스크에 있는 필요한 파일을 가지는 chunk 서버의 위치를 물어봅니다.
    - Chunk 서버는 디스크에 실제 데이터를 저장합니다. 모든 chunk는 서버 장애를 대비하여 여분을 생성하기 위해 세 개의 다른 chunk 서버에 복제됩니다. 마스터 서버를 통해 지정되면, 클라이언트 응용프로그램은 chunk 서버로부터 직접 파일을 가져옵니다.
  • 서비스를 시작한 새로운 응용프로그램은 기존의 GFS 클러스터를 사용하거나 자신을 위한 클러스터를 만들 수 있습니다. 데이터센터를 가로질러 프로세스를 제공하는 하는 것을 이해하는 것은 흥미롭습니다.
  • 핵심은 직원들이 그들의 응용프로그램을 위한 선택을 확신할 수 있는 충분한 인프라입니다. GFS는 개별 응용프로그램의 요구에 맞출 수 있습니다.

  • MAPREDUCE를 사용하여 데이터로 무엇인가를 하라

  • 훌륭한 저장 시스템을 가지고 있다면, 그 많은 데이터로 무엇인가를 해야겠지요. 1000대의 장비에 저장된 수TB 데이터가 있다고 생각해봅시다. 데이터베이스는 이 정도 수준을 확장하거나 비용대비 효율적인 확장을 할 수 없습니다. 그래서 MapReduce가 도입됩니다.
  • MapReduce는 프로그래밍 모델이고 거대한 데이터 집합을 처리하고 만들어내는 연합된 구현입니다. 사용자는 중간 키/값 쌍 집합을 생성하는 키/값 쌍을 처리하는 map 함수와, 그리고 동일한 중간 키 값으로 연관된 모든 중간 값을 모으는 reduce 함수를 지정합니다. 많은 실 세계 작업이 이 모델로 표현됩니다. 이 함수 스타일로 작성된 프로그램은 자동적으로 병렬화되고 장비들의 거대한 클러스터에서 수행됩니다. run-time system은 입력데이터의 세부적인 파티셔닝, 장비 집합들간의 프로그램 실행 시간조정, 장비 장애 처리, 요구되는 장비간의 통신등을 주의해야 합니다. 이는 병렬과 분산 시스템에 경험이 없는 프로그래머가 거대한 분산 시스템의 자원을 쉽게 활용하게 해 줍니다.
  • MapReduce 를 왜 사용하나요?
    - 많은 장비들간에 작업을 분할하는 멋진 방법입니다.
    - 장비 장애를 처리합니다.
    - 검색과 광고처럼 다른 응용프로그램 종류에서도 동작합니다. 거의 모든 응용프로그램이 map reduce 종류 동작을 가지고 있습니다. 여러분은 유용한 데이터를 미리 처리하고, 단어 개수를 찾을 수 있고, TB 데이터를 정렬할 수 있습니다.
    - 계산은 자동으로 IO 소스에 가깝게 이동할 수 있습니다.
  • MapReduce 시스템은 세 종류의 다른 서버를 가지고 있습니다.
    - 마스터 서버는 map, reduce 서버로 사용자의 작업을 할당합니다. 작업의 상태를 추적합니다.
    - map 서버는 사용자 입력을 받아들이고 이를 map 동작을 수행합니다. 결과는 중간 파일로 기록합니다
    - reduce 서버는 map 서버가 만든 중간 파일을 받아서 reduce 동작을 수행합니다.
  • F예로, 모든 웹 페이지에 있는 단어를 수를 계산하길 바랍니다. GFS에 저장된 모든 페이지를 MapReduce로 전달합니다. 1000 대의 장비에서 동시에 일어나고 모든 조정, 작업 스케쥴링, 장애 처리, 데이터 전송은 자동으로 이뤄집니다.
    - 단계는 다음 처럼 보입니다. The steps look like: GFS -> Map -> Shuffle -> Reduction -> Store Results back into GFS.
    - Shuffling 키 종류를 집계합니다.
    - reductions(축소)는 모든 키/값 쌍을 합계하고 마지막 답을 만듭니다.
  • Google의 색인 파이프라인은 20여 개의 다른 맵 축소를 가지고 있습니다. 파이프라인은 레코드와 합계 키를 가지고 데이터를 봅니다. 두번째 map-reduce에 도착하면, 결과를 취하고 다른 일들을 합니다. 계속 반복합니다.
  • 프로그램은 매우 작습니다. 코드로는 20-50 라인정도로 작습니다e.
  • 문제 중 하나는 낙오자입니다. 낙오자는 다른 것을 따라잡지 못하고 느려지는 계산입니다. 낙오자는 느린 Io(나쁜 컨트롤러) 때문이거나 임시적인 CPU 사용량 급등 때문에 발생합니다. 해법은 같은 계산을 여러 개 수행하고 하나가 완료되면 나머지를 모두 죽이는 것입니다.
  • map과 reduce 간의 데이터 전송은 압축을 사용합니다. 서버에 CPU 제한을 두지 않아 대역폭과 I/O를 절약하기 위해서 데이터 압축과 해제에 사용하는 것이 사리에 맞다는 생각입니다.

  • BITTABLE 에 구조화된 데이터를 저장하기 (Storing Structured Data in BigTable)

  • BigTable 은 TB 수준의 메모리와 PB 수준의 저장공간을 포함하는 큰 규모의 장애를 극복하는 자기 관리 시스템입니다. BigTable 은 초당 수백만개의 읽기/쓰기를 처리할 수 있습니다.
  • BigTable 은 GFS 최상위 단에 구축된 분산 해쉬 메커니즘입니다. BigTable 은 관계형 데이터베이스가 아닙니다. BigTable 은 조인이나 SQL 타입의 질의를 지원하지 않습니다.
  • BigTable 은 키로 구조화된 데이터를 접근하는 검색 메커니즘을 제공합니다. GFS는 불분명한 데이터를 저장하고 많은 응용프로그램 요구는 구조를 가지는 데이터를 가지는 것입니다.
  • 상용 데이터베이스는 간단하게 이 정도의 확장을 지원하지 않으며, 1000대의 장비에 걸쳐 동작하지 않습니다.
  • 저수준 저장시스템을 제어하여 Google은 더 많은 시스템 제어와 시스템을 향상시키는 영향력을 얻었습니다. 예로, Google이 데이터센터를 가로지는 동작을 쉽게 만든다면, 만들 수 있습니다.
  • 시스템이 동작중일 때 장비를 추가하거나 제거할 수 있으며, 시스템은 그대로 동작합니다.
  • 모든 데이터 아이템은 저수준 키나 컬럼키, 타임스탬프로 접근할 수 있는 셀에 저장됩니다.
  • 모든 로우는 하나 이상의 tablets 에 저장됩니다. Tablets은 SSTable이라 부르는 데이터 포멧인 연속된 64KB 블록입니다.
  • BigTable 은 3개의 다른 서버를 가집니다:
    - 서버는 tablets을 tablet 서버에 할당합니다. 마스터 서버는 tablet이 어디에 있는지 추적하고 필요에 따라 작업을 재분배합니다.
    - tablet 서버는 tablet을 위한 읽기/쓰기 요청을 처리합니다. Tablet 서버는 tablet이 (보통 100-200MB) 크기 제한을 넘으면 tablet을 분할합니다. Tablet 서버에 장애가 발생하면, 100개의 tablet 서버가 새로운 tablet을 가져가고 시스템은 복구됩니다.
    - Lock 서버는 분산 락 서비스를 수행합니다. 쓰기를 위해 tablet을 여는 동작은, 마스터 중재, 접근 제어 검사는 상호 배제를 필요로 합니다.
  • 지역화 그룹은 더 나은 참조의 지역화를 위해 관려된 데이터들을 물리적으로 저장하는데 사용됩니다.
  • tablet은 가능한만큼 RAM에 캐쉬됩니다.

  • Hardware

  • 아주 많은 장비를 사용할 때 어떻게 비용을 절약하고 전원을 효율적으로 사용하게 구축하겠습니까?
  • 극도로 저렴한 하드웨어를 사용하고 하드웨어의 죽음을 처리하는 소프트웨어를 상단에 구축하세요.
  • 실패하기 쉬운 인프라보다는 높은 신뢰성을 가진 컴포넌트로 구축한 1000대의 컴퓨터 능력은 비용대비 33배나 증가시켜줍니다. 업무에 이 전략을 통해 신뢰 할 수 없는 정점에 신뢰성을 구축해야 합니다.
  • Linux, in-house rack design, PC class mother boards, low end storage.
  • 성능을 기준으로 와트당 가격은 좋아지지 않고 있습니다. 거대한 전원과 냉각 문제가 있습니다.
  • 코로케이션을 섞어서 사용하고 그들만의 데이터센터를 이용합니다.

  • 다양한 것들(Misc)

  • QA를 기다리지 말고 재빨리 변경사항을 적용하세요.
  • 라이브러리는 프로그램을 구축하는 지배적인 방법입니다.
  • 몇몇 응용프로그램은 크롤링 처럼 서비스로 제공됩니다.
  • 인프라가 응용프로그램의 버전을 처리하기 때문에 google은 응용프로그램이 깨지는 공포없이 출시할 수 있습니다.

  • 구글의 미래 방향 (Future Directions for Google)

  • 지리 분산 클러스터 지원(Support geo-distributed clusters).
  • 모든 데이터를 위해 단일한 글로벌 네임스페이스를 만들기. 현재 데이터는 클러스터에 따라 다르게 사용됩니다.
  • 더 많이 더 좋게 데이터와 계산의 자동화된 이전 .
  • 네트워크 파티셔닝에 따라 넓은 지역 복제로 연결될 때 발생하는 일치성 이슈를 해결 (클러스터가 관리나 정전 때문에 오프라인이되어도 서비스를 유지하는 것 같은).

  • 배운 교훈

  • 인프라는 경쟁우위입니다(Infrastructure can be a competitive advantage). ). Google에서는 틀림없습니다. Google은 새로운 인터넷 서비스를 빠르고, 저렴하게, 소수의 경쟁자들이 할 수 있는 것처럼 확장가능하게 출시합니다. 많은 회사들은 완전하게 다른 접근법을 가지고 있습니다. 많은 회사들은 인프라를 비용으로 다룹니다. 각 그룹은 완전하게 다른 기술을 사용하고 거의 계획하지 않으며 시스템 구축법에 대한 공통점이 없습니다. Google은 스스로를 소프트웨어를 구축하기 위한 매우 신선한 방법을 사용하는, 시스템 엔지니어링 회사로 생각합니다.

  • 여러 데이터 센터로 확장은 아직 해결하지 못한 문제입니다(Spanning multiple data centers is still an unsolved problem). 대부분 웹사이트들은 하나 또는 2개이 데이터 센터에 있습니다. 데이터 센터간을 가로질러 완벽하게 웹사이트를 분산하는 방법은 무엇일까요? 우리는 까다롭다고 말할 수 밖에 없습니다..

  • 여러분 스스로 모아서 이런 인프라를 재구축할 시간이 없다면 Hadoop을 눈여겨 보세요(Take a look at Hadoop) Hadoop은 여기서 설명한 많은 동일한 생각을 구현한 오픈소스 구현입니다.
  • 플랫폼 접근법의 진정한 장점은(An under appreciated advantage) 초보 개발자들이 플랫폼의 최상단에 튼튼한 응용프로그램을 빠르고 믿을 수 있게 만들 수 있다는 것입니다. 모든 프로젝트들이 동일한 분산 인프라를 만들 필요하가 있다면 누가 어떻게 하는지 알아야 하는 사람들이 상대적으로 드물기 때문에 여러분은 어려움에 봉착합니다.

  • 시너지는 항상 허풍만은 아닙니다(Synergy isn't always crap).시스템의 모든 부분이 함께 동작하도록 하면 하나의 향상은 모든 것에 도움이 됩니다. 파일시스템을 향상시키면 모든 사람은 즉시 분명하게 이득을 봅니다. 모든 프로젝트가 다른 파일 시스템을 사용하면 전체 스택에서 지속적으로 증가하는 개선이 없습니다.

  • 시스템이 다운되지 않게 동작하는 자기관리 시스템을 구축하세요(Build self-managing systems that work without having to take the system down). 이렇게 하면 서버들간의 자원을 쉽게 재배치하고, 동적으로 가용성을 더할 수 있고, 장비를 offline 시키고, 우아하게 업그데이드를 처리할 수 있습니다.

  • 다윈 인프라를 만드세요(Create a Darwinian infrastructure). 병렬로 시간을 소모하는 동작을 수행하고 승자를 취하세요.

  • 학술적인 것을 잊지 마세요(Don't ignore the Academy). A학계는 제품환경으로 옮겨지지 않은 좋은 아이디어를 많이 가지고 있습니다. Google이 이룩한 대부분은 기술이전의 것이었지만 대규모 배치 이전은 아니었습니다.

  • 압축을 고려하세요(Consider compression). 주위에 많은 CPU를 가지고 있고 IO에 제한이 있을 때 압축은 좋은 옵션입니다.
  • AND

    Collaborative Map-Reduce in the Browser

    After immersing yourself into the field of distributed computing and large data sets you inevitably come to appreciate the elegance of Google's Map-Reduce framework. Both the generality and the simplicity of its map, emit, and reduce phases is what makes it such a powerful tool. However, while Google has made the theory public, the underlying software implementation remains closed source and is arguably one of their biggest competitive advantages (GFS, BigTable, etc). Of course, there is a multitude of the open source variants (Apache Hadoop, Disco, Skynet, amongst many others), but one can't help but to notice the disconnect between the elegance and simplicity of the theory and the painful implementation: custom protocols, custom servers, file systems, redundancy, and the list goes on! Which begs the question, how do we lower the barrier?

    Massively Collaborative Computation

    After several iterations, false starts, and great conversations with Michael Nielsen, a flash of the obvious came: HTTP + Javascript! What if you could contribute to a computational (Map-Reduce) job by simply pointing your browser to a URL? Surely your social network wouldn't mind opening a background tab to help you crunch a dataset or two!

    Instead of focusing on high-throughput proprietary protocols and high-efficiency data planes to distribute and deliver the data, we could use battle tested solutions: HTTP and your favorite browser. It just so happens that there are more Javascript processors around the world (every browser can run it) than for any other language out there - a perfect data processing platform.

    Google's server farm is rumored to be over six digits (and growing fast), which is an astounding number of machines, but how hard would it be to assemble a million people to contribute a fraction of their compute time? I don't think it's far-fetched at all as long as the barrier to entry is low. Granted, the efficiency of the computation would be much lower, but we would have a much larger potential cluster, and this could enable us to solve a whole class of problems previously unachievable.

    Client-Side Computation in the Browser

    Aside from storing and distributing the data the most expensive part of any job is the CPU time. However, by splitting the data into small and manageable chunks, we could easily construct an HTTP-based workflow to let the user's browser handle this for us:

    The entire process consists of four easy steps. First, the client requests to join the cluster by making a request to the job-server which tracks the progress of the computation. Next, the job-server allocates a unit of work and redirects (301 HTTP Redirect, for example) the client to a URL which contains the data and the Javascript map/reduce functions. Here is a sample for a simple distributed word-count:

    <html>
      <head>
        <script type="text/javascript">
     
          function map() {
            /* count the number of words in the body of document */
            var words = document.body.innerHTML.split(/\\n|\\s/).length;
            emit('reduce', {'count': words});
          }
     
          function reduce() {
            /* sum up all the word counts */
            var sum = 0;
            var docs = document.body.innerHTML.split(/\\n/);
            for each (num in docs) { sum+= parseInt(num) > 0 ? parseInt(num) : 0 }
            emit('finalize', {'sum': sum});
          }
     
          function emit(phase, data) { ... }
        </script>
      </head>
     
      <body onload="map();">
        ... DATA ...
      </body>
    </html>
     

    Once the page is loaded and the Javascript is executed (which is getting faster and faster with the Javascript VM wars), the results are sent back (POST) to the job-server, and the cycle repeats until all jobs (map and reduce) are done. Hence joining the cluster is as simple as opening a URL and distribution is handled by our battle-tested HTTP protocol.

    Simple Job-Server in Ruby

    The last missing piece of the puzzle is the job server to coordinate the distributed workflow. Which, as it turns out, takes just thirty lines of Ruby with the help of the Sinatra web framework:

    require "rubygems"
    require "sinatra"
     
    configure do
      set :map_jobs, Dir.glob("data/*.txt")
      set :reduce_jobs, []
      set :result, nil
    end
     
    get "/" do
      redirect "/map/#{options.map_jobs.pop}" unless options.map_jobs.empty?
      redirect "/reduce"                      unless options.reduce_jobs.empty?
      redirect "/done"
    end
     
    get "/map/*"  do erb :map,    :file => params[:splat].first; end
    get "/reduce" do erb :reduce, :data => options.reduce_jobs;  end
    get "/done"   do erb :done,   :answer => options.result;     end
     
    post "/emit/:phase" do
      case params[:phase]
      when "reduce" then
        options.reduce_jobs.push params['count']
        redirect "/"
     
      when "finalize" then
        options.result = params['sum']
        redirect "/done"
      end
    end
     
    # To run the job server: 
    # > ruby job-server.rb -p 80 
     

    That's it. Start up the server and type in the URL in your browser. The rest is both completely automated and easily parallelizable - just point more browsers at it! Add some load balancing, a database, and it may be just crazy enough that it might actually work.

    브라우저에 Map-Reduce를 적용한 분산 시스템 만들기

    스토리지나 데이터의 분산도 좋지만 사실 가장 비용이 드든건 CPU Time입니다.
    이 CPU 자원을 잘게 쪼개서 여러 컴퓨터에 분산시킬 수 있다면 좋겠지요..
    그런데 브라우저 사용자의 HTTP 통신을 이용해서 간단하게 분산하는 방법이 있습니다.

    최근 어떤 사이트에 간단하게 브라우저와 Map-Reduce를 이용하여 분산 시스템을 만드는 법에 관한 글이 올라와 소개합니다.
    일단 Flow를 그림으로 보면 아래와 같습니다. 




    설명하자면 이렇습니다.

    먼저 클러스터에 가입하려는 클라이언트(브라우저)가 Job Server에 접속합니다.
    그러면 Job Server는 계산꺼리 데이터를 텍스트 형태로 브라우저에게 보내주는데(HTTP 301같은걸 이용해서),
    이때 자바스크립트 map()함수와 reduce() 함수를 같이 보내줍니다.
    그러면 클라이언트는 자바스크립트로 Map-Reduce를 실행하고 결과를 Job Server에게 돌려줍니다.


    이렇게해서 Job Server는 작업의 조각들을 무수히 많은 대량의 클라이언트들(브라우저)에게 분산시키게 됩니다.


    물론 여기에도 단점이 있을 수 있습니다.
    Job Server가 받을 수 있는 Request의 수는 이론상의 최대 HTTP Request수를 넘을 수 없다는 것,
    HTTP의 특성상 예상치 못한 오류가 생길 수 있다는 것,
    보안에 약할 수 있다는 것 등의 해결해야 할 문제들이 있습니다만..,
    이런 단점들을 조금씩 해결해 나가면 무지하게 큰 클라우드를 손쉽게 만들 수 있을지도 모르겠습니다.
    어쨌든 참 재밌는 아이디어입니다.

    간략하게 설명했습니다만 원본 글에 방문하시면 예제 소스와 함께 좀 더 자세히 보실 수 있습니다.


    출처 : http://kimho.pe.kr/wordpress/?p=14 
    원본 : http://www.igvita.com/2009/03/03/collaborative-map-reduce-in-the-browser/

    AND

    1 MapReduce 소개

    MapReduce는 대량의 자원을 다루는 분산/병렬 시스템의 효율적인 지원을 위한 목적으로 Google에서 만들어낸 프로그래밍 모델이다. 테라바이트 단위의 데이터를 처리해야 하는 Google의 입장에서 분산/병렬 시스템을 지원하기 위한 이러한 툴의 개발은 필연적인 요구사항이였을 것이다. 분산/병렬 시스템의 효과적인 지원을 위해서는 다음의 사항들이 만족되어야 한다.
    1. 병렬처리 : 하나의 거대한 데이터는 여러개의 분산된 시스템으로 보내어져서 병렬적으로 처리될 수 있어야 한다.
    2. fault-tolerance : 병렬시스템중 몇개에 문제가 생기더라도 전체 시스템에 영향을 주면 안된다. 자동으로 관리할 수 있어야 한다.
    3. 데이터분산 및 로드밸런싱

    2 프로그래밍 모델

    용어에서 알 수 있듯이 MapReduce 는 Map과 Reduce가 합쳐진 용어로, Map 함수와 Reduce 함수의 조합을 통해서 분산/병렬 시스템운용을 지원한다. MapReduce는 데이터를 {Key, Value} 의 쌍으로 만들고 이를 처리하는 프로세스를 가진다.

    Map은 사용자 정의 자료구조이며, 입력데이터에서 Key/Value 쌍으로 이루어진 중간 데이터 형태의 데이터를 만들어낸다. MapReduce 라이브러리는 Value에 대해서 Key I를 함께 관리한다. 그리고 이 중간데이터는 Reduce 함수로 넘겨진다.
    Reduce 함수역시 유저에 의해서 작성되며, Key I와 Key I에 대한 Value를 받아들이게 된다. 그리고 Key값을 이용해서 Value값을 합치게 된다.

    3 MapReduce 테스트

    그럼 MapReduce 를 테스트 프로그램의 예를 들어서 이해를 해보도록 하겠다.

    만들고자 하는 프로그램은 여러개의 문서로부터 각각의 단어가 몇개씩 있는지를 검사하는 프로그램이다. 제대로 테스트 하기 위해서는 분산시스템 환경을 만들어야 겠지만, 상황이 여의치 않으므로 로컬시스템에서 IPC를 이용해서 리모트 분산 환경을 흉내내도록 하겠다.

    mapreduce.png

    분석해야 하는 여러개의 입력 문서를 fork(2)된 worker 프로세스가 읽어들여서 Map으로 만든다음, 그 결과를 중간파일(Intermediate Files)로 저장한다. 저장한 중간파일은 다시 Recude worker 프로세스가 읽어들여서 최종 결과파일을 생성한다.

    이를 리모트환경에서 구현을 한다면 Map worker 프로세스가 생성한 중간파일은 로컬 파일시스템에 저장되고, 원격지에 설치되어 있는 Reduce worker 프로세스가 파일을 잃어 가는 형식이 될것이다. User 프로그램은 각각의 worker프로세스에 작업을 할당하고 관리하는 일을 하게 된다.

    로컬시스템에서 위의 환경을 흉내내고자 한다면 Reduce worker 프로세스가 IPC를 이용해서 중간파일을 읽어 가도록 바꾸면 될것이다.

    3.1 응용

    위의 구조는 MapReduce 시스템의 구조를 단적으로 보여준다. 다만 응용범위와 환경에 따라서 다양한 방식으로의 구성이 가능할 것이다. 여기에서는 몇개의 영문서에서 단어를 카운팅하는 카운팅엔진으로 구현응용에 대해서 알아보도록 하겠다.

    3.1.1 전체 흐름

    단순하게 생각하면, 파일단위로 map worker에 처리를 넘기도록 하면 되겠지만 이는 제대로된 병렬/분산 환경이라고 보기는 힘들다. 어떤 파일은 1Mega이고 어떤 파일은 100Mega일 수 있기 때문이다. 그러므로 여러개의 파일을 하나의 파일처럼 인식을 하고, 이것을 일정한 크기로 쪼개어서 읽어들이도록 해야 한다. User Program은 파일의 목록과 크기를 관리한다음에, 각각의 map worker 프로세스에게, 어떤 조각을 처리할지를 알려주는 역할을 한다. 이를 위해서 User Program은 파일의 목록과 크기 뿐만 아니라, 해당 Worker가 파일의 범위를 찾아갈 수 있도록 offset정보도 유지를 해야 한다.

    1. User Program은 효율적인 병렬/분산처리가 가능하도록 파일을 일정한 크기를 가지는 M 개의 조각으로 쪼갠다.
    2. User Program에는 Master이라는 특별한 프로세스가 존재한다. Master은 worker에게 M map과 R reduce를 할당하며, 각 worker의 상태를 관리한다.
    3. worker은 할당된 문서를 읽어들인다음 유저정의 Map 함수를 이용해서 key/value 형태로 데이터를 읽어들인다. Map함수는 만들어진 key/value를 buffer 메모리에 저장한다. 이 경우 key는 파일명이 될 것이고, value는 {단어,count}가 될 것이다.
    4. buffer 메모리(혹은 파일)에 있는 key/value는 주기적으로 지역파일에 쓴다. 이 파일은 master에 의해서 관리되며, reduce worker에 할당이 된다.
    5. reduce worker이 master로 부터 신호를받았다면, map worker에 의해서 지역파일에 씌여진 buffer 데이터를 가져온다. master와 reduce worker와의 통신은 remote procedure call등을 이용할 수 있을 것이다. 중간파일을 전부 읽어들였다면, 동일 key값을 이용해서, value와 관련된 필요한 계산을 하면 된다. 하나의 reduce작업에 다양한 종류의 key들이 존재하기 때문에, sort가 된후 작업이 되어질 필요가 있다. 이러한 작업은 상당히 많은 메모리를 차지하게 되는데, 이럴경우 다른 프로그램에 소트를 맡기도록 한다.
    6. reduce worker에서 소트를 해서 유일한 key를 만들어 낼 수 있게 되는데, 이때 사용자 정의된 Reduce 함수를 이용해서, value에 대한 연산을 하면 된다. 연산후 결과는 output 파일로 씌여지게 된다 output 파일로 씌여지게 된다.
    7. 모든 작업이 완료되었다면, reduce worker은 프로그램 리턴값을 User Program에게 넘겨준다.

    3.2 Master 데이터 구조체

    master은 map 작업, recude 작업과 진행상태(휴면,진행중,완료)와 worker 기계에 대한 정보를 유지하고 있어야 한다.
    또한 중간파일을 reduce worker에게 분배하기 위해서, 완전히 작업이 끝난 파일에 대해서 크기를 모두 유지하고 있어야 한다. 그래야지만 reduce worker에게 할당할 데이터의 크기를 결정할 수 있기 때문이다.

    3.3 Fault Tolerance

    이러한 MapReduce 시스템은 크게는 수백에서 수천의 기계를 이용해서 정보를 처리해야 하는 경우가 생기며, 때문에 Fault Tolerance는 매우 중요한 사항이다. 발생할수 있는 Fault의 형태에 따라서 어떻게 대응해야 하는지에 대해서 알아보도록 하자.

    3.3.1 Worker Failure

    worker에 주기적으로 Ping를 보내서 응답을 확인해야 한다. 만약 일정시간동안 응답이 없다면 worker에 문세가 생긴 것으로 간주한다. 이 경우 다른 idle상태의 worker를 찾아서 대신 처리하도록 해야 한다.

    3.3.2 Master Failure

    Master의 문제 해결은 비교적 간단하다. 이전 Master이 진행했던 작업이 중간파일 형태로 남아있고 이를 이용해서 checkpointe를 알아낼수 있다. 고로 그냥 Master를 다시 실행시키기만 하면 된다.

    3.3.3 Semantics in ther Presence of Failures

    3.3.4 Locality

    네트워크 대역폭은 지역 컴퓨팅 환경에 비해서 상대적으로 열악하다. 특히 데이터가 다수의 원격 컴퓨터에 분산되어 있다면, 이를 처리하기 위한 환경을 만드는 것도 매우 힘든 작업이 될 수 있다. 때문에 네트워크 상에 가상의 파일시스템을 만들어서, 마치 로컬 컴퓨팅 환경인것 처럼 만들어줄 필요가 있다.

    Google의 경우 GFS(Google File System)을 만들어서 이 문제를 해결하고 있다. 공개진영 소스에는 GFS(Global File System)가 사용되어지고 있다. 이들 주제는 별도의 페이지를 만들어서 정리해 보고자 한다.

    4 샘플 프로그램

    MapReduce 프로그래밍 모델을 테스트 하기 위해서 문서로부터 단어를 추출해서 카운팅하고, Map Reduce 과정을 거쳐서 최종의 결과물을 만드는 프로그램을 만들어 보도록 하겠다.

    이 예제는 MapReduce의 이론적인 측면을 구현하는데 촛점을 맞출 것이다. Worker 스케쥴, Fault Tolerance 등은 고려되지 않을 것이다. Map Reduce 과정을 거쳐서 생성되는 Output File는 용이한 검색을 지원하기 위한 색인 DB가 될 것이다.

    다음은 우리가 만들 색인 프로그램의 MapReduce 다이어그램이다.

    term.png

    1. 4개의 RFC문서가 주어진다.
    2. map worker에 분배하기 위해서 4개의 문서를 3개의 조각으로 바꾼다.
    3. 3개의 map worker을 실행시키고, 각각의 조각을 읽어와서 <DID, Term> 형식의 데이터를 생성한다.
      이 작업은 병렬적으로 수행된다.
    4. reduce worker에서 <DID, Term> 데이터를 읽어와서 <Term, DID>로 Term Invert한다.
    5. Term Invert된 데이터를 Term.idx 파일에 저장한다.

    이렇게 해서 3개의 <Term, DID> .idx 파일이 생성되었다고 가정을 해보자. 만들어진 결과물이, 색인데이터로써의 기능을 수행하기 위해서는 3개의 데이터를 다시 합쳐서 중복된 Term은 제거하고, 여러개의 문서에 포함되어 있는 Term은 하나의 레코드로 만들어줘야 한다. 아마도 아래와 같은 자료구조를 가질 것이다.
    struct LastIndexResult 
    { 
        string Term; 
        vector<string> DID; 
    } 
    set<LastIndexResult> IndexSet; 
     
    그 다음 위의 정보를 파일로 전부 쓰면 된다. 라고 간단히 설명은 했지만, 쉬운 방법으로 해결할 순 없다. 쉽게 생각해보자면 각각의 .idx파일에 이미 Term으로 정렬된 값이 들어가 있으므로, IndexSet을 만드는게 그리 문제되지 않을 거라 생각할 수 있지만, 문서의 양이 많아질 경우 "엄청난 양의 메모리를 소비"해야 한다는 문제가 생길 수 있기 때문이다. 그러므로 데이터를 전부 메모리에 넣어서 정렬하는 것보다는 정렬된 중간파일을 만들어서 병합시켜주는 과정이 필요하다. 귀찮기는 하지만 .idx의 값들은 모두 정렬되어 있으므로, 중간파일을 만들어서 병합시키고 OUTPUT 파일을 만드는건 어려운 작업은 아닐 것이다.


    색인에서 예제로 제시한 indexer를 수정하는 형태로 만들도록 하겠다.

    5 Nutch의 MapReduce 엔진

    MapReduce는 프로그래밍 모델이고, 실제 활용하기 위해서는 MapReduce프로그래밍 모델이 적용된 MapReduce 엔진이 필요하다. 이 엔진을 위해서는 크게 다음과 같은 3개의 요소가 필요할 것이다.
    • Mapper
      Map Task를 실행하기 위한 프로세스로, 파일을 Split 하고, Split된 각 부분을 읽어서 <Key, Value>로 만들기 위한 function을 가진다. <Key, Value>의 목록은 중간파일 형태로 저장이 될 것이다.
    • Reducer
      Reduce Task를 실행하기 위한 프로세스로, Mapper에 의해서 중간파일 형태로 저장된 <Key, Value>파일을 읽어들여서, 결과파일로 만들어 낸다.
    • Job Tracker
      각 Task를 실행하는 Job을 제어하기 위한 프로세스. Mapper과 Reduce를 실행시키고 Job을 할당한다.

    MapReduce엔진은 일종의 프레임워크라고 볼 수 있으므로, 다양한 Job을 실행할 수 있어야 한다. 때로는 색인파일을 만들어야 하고, 때로는 네트워크 파일시스템을 만들 수 있어야 한다. 그렇다면 주어진일을 할 수 있는 Job을 배포할 수 있도록 시스템/소프트웨어적으로 구성이 되어야 할 것이다.

    Java로 구현할 경우에는 바이트코드를 배포하면 되므로, 시스템이나 운영체제에 관계없이 비교적 쉽게 배포시스템을 만들 수 있을 것이다. Perl, Python등을 이용해서 구현해도 Java와 동일한 효과를 얻을 수 있을 것이다.

    컴파일 언어- C/C++ 같은 -로 구현을 한다면, 시스템과 운영체제에 의존적이 될 것이다. 가장 좋은 방법은 모든 시스템을 동일한 운영체제와 동일한 컴파일러, 라이브러리를 가지도록 세팅 하는 것이다. 꽤나 주의 깊은 작업을 필요로 할 것이고, 독자적인 운영체제 배포판을 하나 만드는게 가장 좋을 것이다.

    C/C++에서 job의 배포는 공유 라이브러리형태로 배포되어야 할 것이다. 무가동 시스템으로 만들려면 동적 라이브러리 형태로 만들어서, signal이 주어질 때, 다운로드 받은 라이브러리를 동적으로 적재시키는 방식을 사용해야 할 것이다.

    6 참고문헌

    1. http://jaso.co.kr/tatter/index.php?pl=133 C언어를 이용한 hadoop 파일 시스템 처리
    2. http://www.jaso.co.kr/tatter/index.php?page=8&setdate=200609 hadoop 살펴보기
    3. http://wiki.apache.org/lucene-hadoop/HadoopMapReduce Hadoop MapReduce
    4. [http]다카하시의 radium software 내의 MapReduce 번역 : 한글문서
    5. [http]쓰레드 베이스의 MapReduce : 한글문서
    6. [http]MapReduce 소개글 : 한글문서

      5,6,7 링크 깨짐... 연결가능한 주소 아시는 분 댓글 부탁드립니다.                                                출처 :wiki



    AND


    얼마전 Yahoo!의 HDFS 팀에서 Multiple nodes를 사용하여 HDFS namenode의 Horizontal Scalability를 향상 시키는 방법을 제안 했었습니다 (HDFS-1052). 그런데 그 뒤로는 Dhruba Borthakur라는 Hadoop 커미터가 Vertical Scalability 개선 방법을 제안했습니다(The Curse of Singletons! The Vertical Scalability of Hadoop NameNode, HDFS-1093, HADOOP-6713). Borthakur에 대해 LinkedIn 에서 찾아보니 현재 Facebook에서 근무하는 Hadoop 엔지니어라고 나오는군요.

    위 두 제안을 보면 Vertical Scalability과 Horizontal Scalability라는 용어가 나옵니다. Vertical Scalability는 시스템의 사양을 향상 시켰을 때 얻는 확장성을 의미합니다. 주로 CPU, Memory, Hard disk 등의 향상을 의미합니다. Hadoop과 같은 분산 시스템에서는 시스템 코어의 수가 늘어나는 것도 Vertical Scalability의 범주로 포함됩니다. 반면 Horizontal Scalability는 시스템의 개수를 늘렸을 때 얻는 확장성을 의미합니다. 예를 들면 노드의 수가 10대에서 20개로 늘어났을 때 얻는 확장성을 의미합니다. scale-up과 scale-out도 각각 같은 의미로 통용됩니다.

    본 포스트에서는 위 두 가지 제안 중에서 Dhruba Borthaku가 제안한 vertical scalability 향상을 위한 제안을 소개합니다. 우선 Dhruba Borthakur라는 해커가 지적한 Hadoop Namenode (현재 Hadoop 0.21)의 병목현상은 다음과 같습니다.

    • Network: Facebook에서 자신이 사용하는 클러스터는 약 2000개의 노드로 구성되어 있으며 MapReduce 프로그램 동작 시 각 서버들은 9개의 mapper와 6개의 reducer가 동작하도록 설정되어 있다고 합니다. 이 구성의 클러스터에서 MapReduce를 동작하면 클라이언트들은 동시에 약 30k 의 request를 NameNode 에게 요청한다고 합니다. 그러나 singleton으로 구현된 Hadoop RPCServer의 Listener 스레드가 모든 메시지를 처리하므로 상당히 많은 지연이 발생하고 CPU core의 수가 증가해도 효과가 없었다고 합니다.
    • CPU: FSNamesystem lock 메카니즘으로 인해 namenode는 실제로는 8개의 core를 가진 시스템이지만 보통 2개의 코어밖에 활용되지 않는다고 합니다. Borthakur에 의하면 FSNamesystem에서 사용하는 locking 메커니즘이 너무 단순 하고 HADOOP-1269 를 통해 문제를 개선 시켰음에도 여전히 개선의 여지가 있다고 합니다.
    • Memory: Hadoop의 NameNode는 논문 내용에 충실하게 모든 메타 데이터를 메모리에 유지합니다. 그런데 Borthakur가 사용하는 클러스터의 HDFS에는 6천만개의 파일과 8천만개의 블럭들이 유지하고 있는데 이 파일들의 메타데이터를 유지하기 위해 무려 58GB의 힙공간이 필요했다고 합니다.

    Borthakur가 이 문제를 해결하기 위해 제안했던 방법은 다음과 같습니다.

    • RPC Server: singleton으로 구현되었던 Listener 스레드에 Reader 스레프 풀을 붙였다고 합니다. 그래서 Listener 스레드는 connection 요청에 대한 accept 만 해주고 Reader 스레드 중 하나가 RPC를 직접 처리하도록 개선했다고 합니다. 결과적으로 다량의 RPC 요청에 대해 더 많은 CPU core들을 활용할 수 있게 되었다고 합니다(HADOOP-6713).
    • FSNamesystem lock: Borthakur는 파일에 대한 어떤 operation이 있을 때 lock이 걸리는지 통계를 내고 그 결과로 파일과 디렉토리의 상태를 얻을 때와 읽기 위해 파일을 열 때 걸리는 lock이 전체 lock의 90%를 차지 한다는 것을 밝힙니다. 그리고 저 두 파일 operation들은 오직 read-only operation 이기 때문에 read-write lock 으로 바꾸어 성능을 향상 시켰다고 합니다(HADOOP-1093). 이 부분은 MapReduce 논문(The Google File System) 4.1절 Namespace Management and Locking 에도 설명이 잘 되어 있습니다. 이미 MapReduce에서는 namespace의 자료구조에서 상위 디렉토리에 해당하는 데이터에는 read lock을 걸고 작업 디렉토리 또는 작업 파일에는 read 또는 write lock을 걸어 가능한 동시에 다수의 operation들이 공유 데이터에 접근하게 하면서도 consistency를 유지하는 방법을 설명하고 있습니다. 아마도 file 에 대한 append가 Hadoop 0.20 버전에 추가 된 것 처럼 논문에 설명이 있음에도 구현이 되지 않은 부분이었나 봅니다. 자세한건 소스를 분석해 봐야 알 수 있을 것 같습니다.

    그러나 메모리에 대한 문제는 아직 해결하지 못했다고 합니다. 그래도 Borthakur에 의하면 위 두 가지 문제점을 해결한 것만으로 무려 8배나 scalability를 향상 시켰다고 합니다.

    출처 : 최현식님 블로그

    AND

    질문 :
    하둡의 HDFS나 GFS그냥 하나의 namenode 즉, 메타데이터 서버에만 메타데이터들을 두고관리하는 것인가요? 

    가만히 보니 그러기엔 병목현상이 너무 심해질 것 같아서요.

    다른 분산파일 시스템들도, 하나의 메타데이터 서버만을 두진 않는걸로 알고있습니다.

    일반적으로 메타데이터들을 여러개 묶어 클러스터화 시켜서 , 관리하는 걸로 알고있는데요.

    hadoop 의 HDFS 나 GFS에서 사용하는 메타데이터 자체에 대한 관리는 어떻게 이루어지나요?

    여러개의 메타데이터서버를 두어 분산시켜저장해두는 것인가요?


    답변 : 
    GFS나 HDFS는 하나의 master node가 모든 메타데이터를 관리하고,
    메타데이터를 효율적으로 관리하기 위해 특별히 신경쓰는게 없습니다.
    왜냐하면 그래도 master node에 병목 현상이 나타나기 어려운
    특별한 환경을 위해 설계되었기 때문입니다.

    이들이 가정한 환경은,
    1) 주로 수백MB~GB급의 대용량 파일들을 다루고,
    2) small/random i/o는 거의 없는 경우입니다.
    그렇기 때문에 I/O에 비해서 메타데이터 관리 비용이 크지 않아서
    master/slave architecture로 설계된 것입니다.

    물론 위와 같은 환경에서도 전체 노드 수가 무한히 많아지면
    master node에 병목현상이 나타날 수는 있겠으나,
    현재 구글, 야후 등에서 수 천대 규모로도 잘 운영하고 있는 것으로 봐서는
    1대의 master node로도 필요한 만큼의 scalability(확장성)를 얻을 수 있다고 볼 수 있죠."
    -------------------------------------------------------------------------------------
    깔끔하다...
                                                                   내 질문에 대한 kiast 이대우님의 답변...

    감사합니다.
    AND

    Running Hadoop On Ubuntu Linux (Single-Node Cluster)

    Hadoop설치 과정 한글화  by 유창훈

    원문 http://www.michael-noll.com/tutorials/running-hadoop-on-ubuntu-linux-single-node-cluster/

     환경 Ubuntu 10.10 , ubuntu 10.04 LTS도 동일함  ,Hadoop 0.20.2

     

     1.우분투에서 제공하는 편리한 설치를 위해 아카이브 추가한다.

     sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"

    2.소스 리스트를 업데이트한다.

     sudo apt-get update

    3.Sun-java6-jkd를 설치한다.

     sudo apt-get install sun-java6-jdk

    4. ssh 서버설치
      sudo apt-get install ssh 로 ssh설치.

    5. Java가 잘 설치되었나 확인

      Java –version , javac -version이라고 해서 정상적으로 버전 정보가 뜨면 ok

    6 이부분은 꼭 필요한 부분은 아니며 보안이나 권한, 백업등을 위해 hadoop그룹과 유저를 추가하는 과정이다.

      sudo addgroup hadoop

      sudo adduser –ingroup hadoop hadoop

    7.다음으로  SSH  에 대한 환경설정 이다

      Hadoop 은 노드의 관리를 위해서 SSH의 접근을 요구한다. 예를들어 원격으로 제어할 경우.  지금우리는  싱글 노드를 위한 설치 과정을 보고있다. 그러므로 우리는 localhost 로의 접근을 위해 SSH의 환경설정을 할 필요가 있다.

      여기서 SSH의 설치 운영 및 공개키 인증을 통한 환경설정은 가능하다고 가정한다. 그렇지 않으면 여러 이용가능한 안내서를 찾아보라.

      첫째로 우리는 hadoop user을 위한 SSH키를 생성한다.


    user@ubuntu:~$ su - hadoop 

    hadoop@ubuntu:~$ ssh-keygen -t rsa -P ""

    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/hadoop/.ssh/id_rsa):
    Created directory '/home/hadoop/.ssh'.
    Your identification has been saved in /home/hadoop/.ssh/id_rsa.
    Your public key has been saved in /home/hadoop/.ssh/id_rsa.pub.
    The key fingerprint is:
    9b:82:ea:58:b4:e0:35:d7:ff:19:66:a6:ef:ae:0e:d2 hadoop@ubuntu
    The key's randomart image is:
    [...snipp...]

    hadoop@ubuntu:~$

    E. 두번째 라인의  ssh 키 생성은 “암호” 원래 이렇게 들어가는 걸 추천하는데 지금 우리의 경우는 암호를 넣지 않고 진행하도록 한다.

    F. 인증키를 방금생성한 공개키로 대체한다.

    hadoop@ubuntu:~$ cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys

    H.마지막으로 SSH setup 테스트를 위해 hadoop user로 local machine 에서 연결을 수행해 본다. 이 과정은 또한 당신의 컴퓨터에 hadoop user 에 대한 fingerprint 를 남기는 과정이다. 만약 ssh에서 다른 포트를 사용한다면 home/.ssh/config 을 수정해야 하는데, 수정을 위한 도움을 받기위해선 맨위에 링크에서 찾아보도록하자.

    hadoop@ubuntu:~$ ssh localhost

    The authenticity of host 'localhost (::1)' can't be established.
    RSA key fingerprint is d7:87:25:47:ae:02:00:eb:1d:75:4f:bb:44:f9:36:26.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
    Linux ubuntu 2.6.32-22-generic #33-Ubuntu SMP Wed Apr 28 13:27:30 UTC 2010 i686 GNU/Linux
    Ubuntu 10.04 LTS
    [...snipp...]
    hadoop@ubuntu:~$
        
    I. 디버깅을 위해선  ssh –vvv localhost 를 이용하면 된다.

    J. SSH server 환경설정을 체크하기위해 /etc/ssh/sshd_config 옵션중 PubkeyAuthentication(yes로 세팅되어있어야한다) 와 allowusers(if this option is active, add the hadoop user to it).
    사용자가 SSH  서버에 환경설정 파일을 바꿨다면 꼭 sudo /etc/init.d/ssh reload 명령어를 써야만 한다. 
    IPv6해제A.     우분투에서는 0.0.0.0 이라는 주소의 사용으로 인해 IPv6에서 문제가 발생한다. 필자의 경우에는 IPv6를 사용할 일이 없기 때문에 간단하게 사용하지 않는다.
     IPv6 를 해제하기 위해서 우분투 10.04 LTS버전에서는 /etc/sysctl.conf 파일을 열어 다음과 같이 추가한다.
    (단 이파일은 관리자계정에서수행하도록한다 )

    #disable ipv6
    net.ipv6.conf.all.disable_ipv6 = 1
    net.ipv6.conf.default.disable_ipv6 = 1
    net.ipv6.conf.lo.disable_ipv6 = 1

    그리고 cat /proc/sys/net/ipv6/conf/all/disable_ipv6를통해서 값이 0이 나오면 ipv6가 enable이란뜻이고 1이면 disable(이게나와야된다)

    K.위의 방법 대신에 다음과 같은 방법을 사용할 수 있다. 나중에 하둡설치다하고

     ~/conf/hadoop-env.sh수정

    ------------

    Export HADOOP_OPTS = -Djava.net.preferIPv4Stack=true
    -----------

    이제  hadoop 을 인스톨해 보자여기서는  0.20.2 버전을 사용한다.  파일은http://www.apache.org/dyn/closer.cgi/hadoop/core 요기서 받자 버전 잘확인하고

    cd /usr/local
    sudo mkdir hadoop                             
    sudo tar xzf hadoop-0.20.2.tar.gzsudo mv hadoop-0.20.2 hadoop           
    sudo chown –R hadoop:hadoop hadoop


    이렇게 하면  hadoop 이하 모든 폴더의 소유자가 hadoop으로 바뀐다.  HDFS에 대해서는 각자 이론을 쌓았으리라 생각된다. -->> 같이 공부합시다 ㅎ.ㅎ

     

    환경설정

    이번 안내서의 목적은 싱글노드를 위한 하둡셋팅이다.

    Hadoop-env.sh여기서는 JAVA_HOME 경로 수정만 하면된다.

    일단 하둡설치 경로에 위에서는/usr/local/hadoop/conf/hadoop-env.sh 에 JAVA_HOME 항목의 경로를 제대로 지정한다.
    필자는 /usr/lib/jvm/java-6-openjdk 으로 바꾸어 주었다. 

    Conf/*-site.xml

    여기서는 한가지 항목을 수정해야한다. 밑에 빨간 부분만 수정하면된다.
    hadoop-datastore는 mkdir명령어로 만들면된다.
    저부분은 하둡이 데이터 파일을 저장하는 곳이 되겠다. 필자의 경우에는  /usr/local/hadoop/hadoop-datastore/hadoop-hadoop로 지정하였고 이전에 했던것처럼 chown hadoop:hadoop /usr/local/hadoop/hadoop-datastore/hadoop-hadoop  이렇게 하고 또한 sudo chmod 750 /usr/local/hadoop/hadoop-datastore/hadoop-hadoop을  입력한다

    **  hadoop-0.20.2.tar.gz 파일을 풀게되면 hadoop-0.20.2폴더가 생성되는데 필자는 hadoop-0.20.2폴더안의  모든파일을 /usr/local/hadoop/ 아래에 복사하였다.  hadoop-0.20.2 폴더자체를 복사한게 아니고 안에 내용만복사하였다.
    그래서 아래 나오는 경로들은 다음과 같게 되는것이다. 참고. 경로들이야 지정하기 나름이다. 편의대로하기바란다.


    이제 다음 3개의 파일에 아래와같이 수정하여 준다.
    /usr/local/hadoop/conf/core-site.xml:

    <!-- In: conf/core-site.xml -->
    <configuration>
    <property> 
    <name>hadoop.tmp.dir</name> 
    <value>/your/path/to/hadoop/tmp/dir/hadoop-${user.name}</value> 
    <description>A base for other temporary directories.</description>
    </property>


    <property> 
    <name>fs.default.name</name> 
    <value>hdfs://localhost:54310</value> 
    <description>The name of the default file system.  A URI whose  scheme and authority determine the FileSystem implementation.  The  uri's scheme determines the config property (fs.SCHEME.impl) naming  the FileSystem implementation class.  The uri's authority is used to  determine the host, port, etc. for a filesystem.</description>
    </property>
    </configuration>


    usr/local/hadoop/conf/mapred-site.xml

    :<!-- In: conf/mapred-site.xml -->
    <configuration>
    <property> 
    <name>mapred.job.tracker</name> 
    <value>localhost:54311</value> 
    <description>The host and port that the MapReduce job tracker runs  at.  If "local", then jobs are run in-process as a single map  and reduce task.  </description>
    </property>
    </configuration>


    /usr/local/hadoop/conf/hdfs-site.xml

    :<!-- In: conf/hdfs-site.xml -->
    <configuration>
    <property> 
    <name>dfs.replication</name> 
    <value>1</value> 
    <description>Default block replication.  The actual number of replications can be specified when the file is created.  The default is used if replication is not specified in create time.  </description>
    </property>
    </configuration>

    네임노드 포멧하기이제 하둡 로컬 파일시스템을 포멧해야한다. 처음에만 해주면된다. 포멧시에는 일반 디스크 포멧처럼 하둡의 데이터 들은 지워지게 되므로 주의한다.

    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop namenode -format


    10/05/08 16:59:56 INFO namenode.NameNode: STARTUP_MSG:
    /************************************************************
    STARTUP_MSG: Starting NameNode
    STARTUP_MSG:   host = ubuntu/127.0.1.1
    STARTUP_MSG:   args = [-format]
    STARTUP_MSG:   version = 0.20.2
    STARTUP_MSG:   build = https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20 -r 911707; compiled by 'chrisdo' on Fri Feb 19 08:07:34 UTC 2010
    ************************************************************/
    10/05/08 16:59:56 INFO namenode.FSNamesystem: fsOwner=hadoop,hadoop
    10/05/08 16:59:56 INFO namenode.FSNamesystem: supergroup=supergroup
    10/05/08 16:59:56 INFO namenode.FSNamesystem: isPermissionEnabled=true
    10/05/08 16:59:56 INFO common.Storage: Image file of size 96 saved in 0 seconds.
    10/05/08 16:59:57 INFO common.Storage: Storage directory .../hadoop-hadoop/dfs/name has been successfully formatted.
    10/05/08 16:59:57 INFO namenode.NameNode: SHUTDOWN_MSG:
    /************************************************************
    SHUTDOWN_MSG: Shutting down NameNode at ubuntu/127.0.1.1
    ************************************************************/

    hadoop@ubuntu:/usr/local/hadoop$ 정상적으로 수행되었다면 위와 같이 표시될 것이다.
    이제 우리의 싱글노드 클러스터를 시작해 보자/usr/local/hadoop/bin/start-all.sh잘될것이다.
    싱글노드 클러스터를 멈추는 방법은  위의 명령어에서 start를 stop로 바꾸면된다.
    그럼 이제 잘 작동되는지 적절한 문서를 하나의 예로 들어 동작시켜보자

    /usr/local/hadoop/bin/start-all.sh이것은 namenode와 datanode, jobtracker과 tasktracker을 수행시킬 것이다. 위에 것들이 잘 동작하는 지 알아보는 방법으로 jps 를 실행시켜보는 것이다.
    /usr/local/hadoop/jps 또한 netstat 를 통해서도 현재 listening중인 포트들을 확인할 수 있다.
    sudo netstat -plten | grep java 만약 어떠한 에러가 있다면 /usr/local/hadoop/logs폴더를 살펴보기 바란다.  


    MapReduce job 예제 따라 하기

  • The Outline of Science, Vol. 1 (of 4) by J. Arthur Thomson
  • The Notebooks of Leonardo Da Vinci
  • Ulysses by James Joyce
  • 위의 예제를 바탕으로 단어의 개수를 세는 일을 수행해 보도록 하겠다. 위의 글을 /tmp/gutenberg 폴더에 저장 하도록한다

    hadoop@ubuntu:~$ ls -l /tmp/gutenberg/

    total 3592
    -rw-r--r-- 1 hadoop hadoop  674425 2007-01-22 12:56 20417-8.txt
    -rw-r--r-- 1 hadoop hadoop 1423808 2006-08-03 16:36 7ldvc10.txt
    -rw-r--r-- 1 hadoop hadoop 1561677 2004-11-26 09:48 ulyss12.txt

    hadoop@ubuntu:~$ 

    MapReduce jpg을  수행하기 전에 반드시 로컬 파일시스템에서 하둡의 HDFS로 복사를 해야한다.

    다음과 같이 수행하도록하자


    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -copyFromLocal /tmp/gutenberg gutenberg

    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -ls
    Found 1 items
    drwxr-xr-x   - hadoop supergroup          0 2010-05-08 17:40 /user/hadoop/gutenberg

     

    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -ls gutenberg
    Found 3 items
    -rw-r--r--   1 hadoop supergroup     674762 2010-05-08 17:40 /user/hadoop/gutenberg/20417.txt
    -rw-r--r--   1 hadoop supergroup    1573044 2010-05-08 17:40 /user/hadoop/gutenberg/4300.txt
    -rw-r--r--   1 hadoop supergroup    1391706 2010-05-08 17:40 /user/hadoop/gutenberg/7ldvc10.txt

    이제 실제로 수행하도록 해보자.

     

    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop jar hadoop-0.20.2-examples.jar wordcount gutenberg gutenberg-output

    다음과 같은 결과가 나올 것이다.


    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop jar hadoop-0.20.2-examples.jar wordcount gutenberg gutenberg-output

    10/05/08 17:43:00 INFO input.FileInputFormat: Total input paths to process : 3
    10/05/08 17:43:01 INFO mapred.JobClient: Running job: job_201005081732_0001
    10/05/08 17:43:02 INFO mapred.JobClient:  map 0% reduce 0%
    10/05/08 17:43:14 INFO mapred.JobClient:  map 66% reduce 0%
    10/05/08 17:43:17 INFO mapred.JobClient:  map 100% reduce 0%
    10/05/08 17:43:26 INFO mapred.JobClient:  map 100% reduce 100%
    10/05/08 17:43:28 INFO mapred.JobClient: Job complete: job_201005081732_0001
    10/05/08 17:43:28 INFO mapred.JobClient: Counters: 17
    10/05/08 17:43:28 INFO mapred.JobClient:   Job Counters
    10/05/08 17:43:28 INFO mapred.JobClient:     Launched reduce tasks=1
    10/05/08 17:43:28 INFO mapred.JobClient:     Launched map tasks=3
    10/05/08 17:43:28 INFO mapred.JobClient:     Data-local map tasks=3
    10/05/08 17:43:28 INFO mapred.JobClient:   FileSystemCounters
    10/05/08 17:43:28 INFO mapred.JobClient:     FILE_BYTES_READ=2214026
    10/05/08 17:43:28 INFO mapred.JobClient:     HDFS_BYTES_READ=3639512
    10/05/08 17:43:28 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=3687918
    10/05/08 17:43:28 INFO mapred.JobClient:     HDFS_BYTES_WRITTEN=880330
    10/05/08 17:43:28 INFO mapred.JobClient:   Map-Reduce Framework
    10/05/08 17:43:28 INFO mapred.JobClient:     Reduce input groups=82290
    10/05/08 17:43:28 INFO mapred.JobClient:     Combine output records=102286
    10/05/08 17:43:28 INFO mapred.JobClient:     Map input records=77934
    10/05/08 17:43:28 INFO mapred.JobClient:     Reduce shuffle bytes=1473796
    10/05/08 17:43:28 INFO mapred.JobClient:     Reduce output records=82290
    10/05/08 17:43:28 INFO mapred.JobClient:     Spilled Records=255874
    10/05/08 17:43:28 INFO mapred.JobClient:     Map output bytes=6076267
    10/05/08 17:43:28 INFO mapred.JobClient:     Combine input records=629187
    10/05/08 17:43:28 INFO mapred.JobClient:     Map output records=629187
    10/05/08 17:43:28 INFO mapred.JobClient:     Reduce input records=102286

    HDFS의 디렉토리인 guntenberg-output 디렉토리에 결과가 성공적으로 저장 되었는지 확인하도록하자

     

    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -ls
    Found 2 items
    drwxr-xr-x   - hadoop supergroup          0 2010-05-08 17:40 /user/hadoop/gutenberg
    drwxr-xr-x   - hadoop supergroup          0 2010-05-08 17:43 /user/hadoop/gutenberg-output

    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -ls gutenberg-output
    Found 2 items
    drwxr-xr-x   - hadoop supergroup          0 2010-05-08 17:43 /user/hadoop/gutenberg-output/_logs
    -rw-r--r--   1 hadoop supergroup     880330 2010-05-08 17:43 /user/hadoop/gutenberg-output/part-r-00000
    hadoop@ubuntu:/usr/local/hadoop$


    만약 Reduce task를 좀더 늘이고 싶다면 "-D"옵션을 사용할 수 있다.
    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop jar hadoop-0.20.2-examples.jar wordcount -D mapred.reduce.tasks=16 gutenberg gutenberg-output
    하지만 mapred.map.tasks 항목을 사용자가 임의로 수정할 수 는 없다. 오직 mapred.reduce.tasks 뿐이다.

    이제 HDFS로부터 결과를 확인해 보도록 하자


    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -cat gutenberg-output/part-r-00000위와 같은 명령으로 결과를 확인 할 수 있다 .

    하지만 여기서는 로컬 파일 시스템으로 복사하도록 해보자 

     

    hadoop@ubuntu:/usr/local/hadoop$ mkdir /tmp/gutenberg-output
    hadoop@ubuntu:/usr/local/hadoop$ bin/hadoop dfs -getmerge gutenberg-output /tmp/gutenberg-output
    hadoop@ubuntu:/usr/local/hadoop$ head /tmp/gutenberg-output/gutenberg-output
    "(Lo)cra"       1
    "1490   1
    "1498," 1
    "35"    1
    "40,"   1
    "A      2
    "AS-IS".        1
    "A_     1
    "Absoluti       1
    "Alack! 1
    hadoop@ubuntu:/usr/local/hadoop$ 만약 head명령을 사용한다면 처음 10줄만 보여준다. 참고. 
    하둡 웹 인터페이스하둡은 다음의 웹 인터페이스를 제공한다. 편의에 따라 사용하도록하자
    •http://localhost:50030/ – web UI for MapReduce job tracker(s)
    •http://localhost:50060/ – web UI for task tracker(s)
    •http://localhost:50070/ – web UI for HDFS name node(s)

    각 항목마다 로그보기가 있어서 관리적 차원에서 이용할 수 있겠다.

    AND


    hadoop 한글 문서화가 없는 듯하여 내가 직접 번역하기로 하였다. 현재 http://www.michael-noll.com/tutorials/running-hadoop-on-ubuntu-linux-single-node-cluster/ 페이지를 문서화하고 있으며 이로인해 hadoop 공부를 시작하려는 다른 한국인들이 영어로인해 꺼려하지 않았으면 하는 바램이다.
    AND