--------------------------------
原文鏈接:http://blog.csdn.net/amuseme_lu/article/details/5616198
Overview
* 爲什麼要用Mapreduce?
* 什麼是Mapreduce?
* Hadoop的分佈式文件系統
How MapReduce is Structured:
* 函數式程式滿足了分佈式計算的要求
* 大批量的數據處理系統
* 在應用邏輯層面上把很多可靠的因素考慮進來了
MapReduce Provides:
* 自動化的平行&數據分佈
* 高可用性
* 狀態與監控工具
* 爲程序員提供了一種清晰的抽象
Programming Model:
* 來看一下什麼是函數式編程
* 用可實現了下面兩個方法
- map (in_key, in_value) -> (out_key, intermediate_value) list
- reduce (out_key, intermediate_value list) -> out_value list
Map:
* 從數據源中讀取一條條記錄來用做爲Map函數的key和value對,如filename, line, etc..
* map()產生了一個或多箇中間的value值,這些值是由input的輸出key來提供的。
- map (in_key , in_value) -> (out_key, intermediate_value) list
- Example: Upper-case Mapper:
- let map(key ,v ) = emit(k.toUpper(), v.toUpper())
- ("foo","bar") -> ("FOO","BAR")
- ("Foo","other") -> ("FOO","OTHER")
- ("key2","data") -> ("KEY2","DATA")
Explode Mapper:
- let map(k, v) = foreachchar c in v: emit(k,v)
- ("A","cats") -> ("A","c"), ("A","a"),("A","t"),("A","s")
- ("B","hi") -> ("B","h"), ("B","i")
Filter Mapper:
- let map(k, v) = if (isPrime(v)) then emit(k,v)
- ("foo",7) -> ("foo",7)
- ("test",10) -> (nothin)
Changing Keyspaces:
- let map(k, v) = emit(v.length(), v)
- ("hi","test") -> (4,"test")
- ("x","quux") -> (4,"quux")
- ("y","abracadabra") -> (10,"abracadabra")
reduce:
* 當map過程結束後,所有的中間值都會通過唯一的輸出key聚合在一起,來作爲reduce的輸出值
* reudce()方法把這些有相同輸出key的中間值組合成一個或多個最終的值(final values)
* 在實際中,一般一個Key只有一個value
- reduce (out_key, intermediate_value list) -> out_value list
- Example: Sum Reducer
- let reduce(k, vals) =
- sum = 0
- foreach int vin vals:
- sum += v
- emit(k, sum)
- ("A",[42,100,312]) -> ("A",454)
- ("B",[12,6,-2]) -> ("B",16)
- Identity Reducer:
- let reduce(k, vals) =
- foreach v in vals:
- emit(k, v)
- ("A", [ 42, 100, 312]) -> ("A",42),("A",100),("A",312)
- ("B",[12,6,-2]) -> ("B",12),("B",6),("B",-2)
Parallelism
* map() 函數是可以並行運行的,它從不同的輸入數據集中創建了不同的中間值
* reduce() 函數也是並行運行的,各個執行者都有不同的輸出key
* 所有的值都是相互獨立(independently)處理的,也就是說並行處理的節點之間沒有數據上的關聯
* Bottleneck: reduce方法要等map方法完全處理完了才能夠開始運行
- Example: Count word occurrences
- map(String input_key, String input_value):
- // input_key: document name
- // input_value: document contents
- for each word w in input_value:
- emit(w,1);
- reduce(String output_key, Iterator<int> intermediate_values):
- // output_key: a word
- // output_values: a list of counts
- int result = 0;
- for each v in intermediate_values:
- result += v;
- emit(output_key, result);
Combing Phase:
* 在Mapper節點上運行
* "Mini-reduce",只針對map的本地輸出
* 在把數據發到reducer之前減少帶寬的佔用量
* reducer可以被組合,如果它是交互的或有關聯的,如SumReducer。(不明白??)
- WordCountRedux:
- map(String input_key, String input_value):
- // input_key: document name
- // input_value: document contents
- for each word w in input_value:
- emit(w, 1);
- reduce(String output_key, Iterator<int>
- intermediate_values):
- // output_key: a word
- // output_values: a list of counts
- int result = 0;
- for each v in intermediate_values:
- result += v;
- emit(output_key, result);
MapReduce Conclusions
* Maprduce在某些場合被證明是非常有用的抽象
* 很大程度上簡化了大規模計算的複雜度
* 函數式編程的範例被證明可以用來處理大規模應用
* 你可以專心的解決實際問題,其它的事讓library來幫你做吧
-=========================
HDFS
HDFS: Motivation
* 基於Google的GFS
* 大量的冗餘數據分佈式廉價的和不可靠的計算機上
* 爲什麼不使用現有的計算機文件系統呢?
- 不同的數據負載量和設計的優先級
- 不同與其它文件系統的大數據量處理能力
Assumptions
* 組件節點的高失效率
- 廉價的商用組件隨時隨地都可以失效
* "適當" 數量的大(HUGE)文件
- 數量只有幾百萬
- 每一個只有100MB或更大;一般都是幾GB的文件
* 文件大者是寫一次,append很多次
- 大概這些都是並行發生的
* 大量的數據流讀操作
* 大量持久的吞吐量
HDFS Design Decisions
* 文件是以塊的方式進行存儲
- 塊的大小都比一般的文件系統大,一般爲64MB
* 通用複製數據塊來得到高可用性
- 一般每一個數據塊被複製成三份放在不同的數據節點上(DataNodes)
* 單個主節點(NameNode)管理對元數據的讀寫操作
- 簡單的集中式管理
* 沒有數據caching
- 有一點點得利於大規模數據集和流讀取
* 熟悉的和可擴展的API
- 簡化問題;集成分佈式應用
HDFS Architecture
Picture::
Metadata
* 單個NameNode管理所有的元數據
- 文件名,每個文件在DataNodes上的地址
* 這些都存儲在RAM中以提高訪問速度
* 每一個DataNode以"block"爲對象在本地文件系統對文件內容進行存儲和管理
HDFS Conclusions
* HDFS支持在商用硬件平臺上對大規模數據進行處理
- 設計用於支持使用的頻繁失效
- 對於大文件的append和read進行了優化
- 文件系統接口爲不同的工作而定製,但是又對開發者而言保持相對熟悉
- 簡單的解決方案也可以工作,如單個master
* 在單個clusters上可靠的存儲數TB的數據