第一章:初識Hadoop
MapReduce三大設計目標:
- 爲只需要短短几分鐘或幾個小時就可以完成的作業提供服務
- 運行於同一個內部有高速網絡連接的數據中心內
- 數據中心內的計算器都是可靠的、專門的硬件
提供Hadoop支持的公司:Cloudera、Hortonworks、MapR等
MapReduce: input --> map --> shuffle --> reduce --> output
Map: extends Mapper 輸入參數: 輸入鍵、輸入值、輸出鍵、輸出值
Reduce: extends Reducer
Job規定步驟:
- 構造Job,需要指定輸入和輸出數據的路徑
- setMapperClass() 和 setReduceClass(),需要指定需要用的map類型和reduce類型
- setOutputKeyClass() 和 setOutputValueClass()方法控制reduce函數的輸出類型,並且必須和Reduce類產生的相匹配。
- 在設置定義map和reduce函數的類的之後,可以開始運行作業。Job中的waitForCompletion()方法提交作業並等待執行完成。
數據流:
如果一個任務失敗,它將在另一個不同的節點上自動重新調度運行。
Map數確定、分片:Hadoop將MapReduce的輸入數據劃分成等長的小數據塊,稱爲輸入分片
Hadoop爲每個分片構建map任務
最佳分片的大小應該與塊大小相同,確保可以存儲在單個節點上的最大輸入塊的大小
第一個副本存儲在本地節點上,其他複本出於可靠性考慮存儲在其他機器的節點中
Reduce的任務的數:獨立確定
Combiner: 避免map和reduce任務之間的數據傳輸,combinner不能取代reduce函數,只能幫助減少map和reduce之間的數據傳輸量
第三章 Hadoop分佈式文件系統
HDFS以流式數據訪問模式來存儲超大文件
HDFS不適用之處:
- 低時間延遲的數據訪問
- 大量的小文件
- 多用戶寫入,任意修改文件
HDFS塊: 默認128MB,小於一個塊大小的文件不會佔據整個塊的空間
HDFS塊比磁盤的塊大,其目的是爲了最小化尋址開銷
塊抽象優點:
- 一個文件的大小可以大於網絡中任意一個磁盤的容量
- 使用抽象塊而非整個文件作爲存儲單元,大大簡化了存儲子系統的設計。塊只需要存儲大塊數據,而文件的元數據並不需要與塊一同存儲。其他系統也可以單獨管理元數據
- 塊還非常適合用於數據備份進而提供數據容錯能力和提高可用性
顯示塊信息: hdfs fsck / -files -blocks
NameNode: 管理文件系統的命名空間,維護着文件系統樹及整棵樹內所有的文件和目錄。
NameNode在內存中保存文件系統中每個文件和每個數據塊的引用關係,對於一個擁有大量文件的超大集羣來說,內存將成爲瓶頸。
2.x版本引入了namenode擴展,每個namenode管理文件系統命名空間的一部分。
聯邦環境下,每個namenode維護一個命名空間卷(命名空間元數據 + 數據塊池(所有數據塊))
DataNode:是文件系統的工作節點,根據需要存儲並檢索數據塊,並且定期向namenode發送它們所存儲的塊的列表。
NameNode容錯:
- 第一種機制是備份那些組成文件系統元數據持久狀態的文件,在多個文件系統上保存元數據的持久狀態
- 運行一個輔助namenode
塊緩存:
對於訪問頻繁的文件,其對應的塊可能被顯式地緩存在datanode的內存中,以堆外塊緩存的形式存在。可以利用塊緩存的優勢提高讀操作的性能
文件系統的基本操作:
從本地將一個文件複製到HDFS:hadoop fs -copyFromLocal xxxx xxxx
副本系數: drwxr-xr-x 1 tom supergroup 0 2014-10-04 13:22 books
FileSystem基礎類:
IOUtils:
InputStream in = fs.open(new Path(uri));
IOUtils.copyBytes(in,System.out,4096,false);
FSDataInputStream對象 / FSDataOutputStream對象:
FileSystem 的open方法返回的是FSDataInputStream對象
FileStatus() 文件元數據:
FileStatus封裝了文件系統中文件和目錄的元數據,包括文件長度、塊大小、副本、修改時間、所有者、權限信息。
listStatus() 列出文件
globStatus() 文件模式
批量處理。返回路徑格式與指定模式匹配的所有FileStatus對象組成的數組,並按路徑排序
PathFilter對象
用於排除匹配正則表達式的路徑
public class RegexExcludePathFilter implements PathFilter{
private final String regex;
public RegexExcludePathFilter(String regex){
this.regex = regex;
}
public boolean accept(Path path){
return !path.toString().matches(regex);
}
}
fs.globStatus(new Path("/2007/*/*"),new RegexExcludeFilter("^.*/2007/12/31$"))
HDFS讀取數據過程:
- DistributedFileSystem通過使用遠程過程調用(RPC)來調用namenode,確定塊位置
- 這些datanode根據它們與客戶端的距離進行排序(兩個節點的帶寬作爲距離)
- 客戶端選擇連接最近的datanode進行連接,並反覆執行read()
- DFSInputStream關閉與該datanode的連接,然後尋找下一個塊最佳datanode
HDFS寫入數據過程:
- DistributedFileSystem對象調用create()來創建文件
- namenode檢查以確保這個文件不存在以及客戶端有新建文件的權限
- 如果通過,namenode會創建一條新文件記錄
- DistributedFileSystem會返回一個FSDataOutputStream對象,由此客戶端可以開始寫入數據
- DFSOutputStream將它劃分成一個個數據包,並寫入內部隊列
- DataStreamer處理數據隊列,並將數據存儲到合適的datanode中
- 第一個datanode將數據發送給管線中的第二個datanode,第二個datanode將數據發送給管線中的第三個datanode......
在datanode寫入時發生故障時:
關閉管線,從管線中刪除datanode,並基於正常的datanode構建一條新管線,餘下的數據寫入管線中正常的datanode
HDFS複本選擇:
- 運行客戶端的節點上放第一個複本
- 第2個複本放在與第一個不同且隨機另外選擇的機架中節點上
- 第3個複本與第2個複本放在同一個機架上,且隨機選擇另一個節點
HDFS一致性模型:
- 新建一個文件後,在文件系統的命名空間中立即可見
- 但是寫入一個文件並不保證能立即可見
- 當寫入的數據超過一個塊後,第一個數據塊對新的reader就是可見的,當前正在寫入的塊對其他reader不可見
- 強制hflush(),保證所有新的reader均可見
!!hflush() 不保證datanode已經將數據寫到磁盤上,僅保證數據在datanode的內存中(如果斷電,數據會丟失)。Hdfs關閉其實就隱含了執行hflush() 方法
!!爲確保數據寫入到磁盤上,可以用hsync()替代
distcp方法
distcp使用MapReduce作業來實現,複製作業是通過集羣中並行運行map來完成。沒有reduce
hadoop distcp dir1 dir2
-overwirte
-update 僅更新發生變化的文件
-m 指定map數目
-delete 可以刪除目標路徑中任意沒有在源路徑中出現的文件或目錄
-P 文件狀態屬性如權限、塊大小和複本數被保留
爲保證hdfs均衡,可考慮map數量多於節點中的數量
第4章 關於Yarn
Yarn:Yet Another Resource Negotiator
Yarn應用運行機制:
兩個長期運行的守護進程:
- 資源管理器(ResourceManager):監控資源使用
- 節點管理器(Node Manager):啓動和監控容器(Container)
- Containner: 用於執行特定應用程序的進程,有內存、CPU等資源限制
Yarn運行過程:
- 向ResourceManager 提交Yarn應用
- 通過NodeManager啓動Containner
- 一個應用的多個實例都對應一個application master
- Containner通過心跳,向ResourceManager進行通信,Container執行任務
- 一個節點已經運行了別的容器無法再啓動新的容器,如果有應用請求該節點,yarn將嘗試在同一個機架中的其他節點上啓動一個容器,如果不行,則會嘗試集羣中的任意一個節點
- 當啓動一個容器用戶處理hdfs數據塊時,yarn會向存儲數據塊的節點申請容器
- Yarn可以在任意時刻提出申請資源
Yarn與MapReduce 1相對比
MapReduce 1中有兩類守護進程控制着作業執行:
一個Jobtracker以及多個tasktracker
tasktracker在運行任務的同時將運行進度報告發送給jobtracker,jobtracker記錄每項作業任務的整體進度情況
jobtracker 負責作業調度 & 進度監控
MapReduce 1 |
Yarn |
Jobtracker |
ResourceManager、application master、時間軸服務器 |
Tasktracker |
NodeManager |
Slot |
Container |
Yarn優點:
- 可擴展性:MapReduce 1在任務達到4000時會遇到擴展性瓶頸,Yarn利用RM和application master分離架構可將近10000
- 可用性:當服務守護進程失敗時,可以爲另一個守護進程複製接管工作所需的狀態以便繼續服務
- 利用率
- 多租戶:MapReduce僅僅是許多Yarn應用中的一個
Yarn的三種調度:
- FIFO調度器
- 容量調度器:一個獨立的專門的隊列保證小作業提交
- 公平調度器:在運行作業之間動態平衡資源,每個作業都能保證公平共享資源
- 啓動公平調度器:yarn.resourcemanager.scheduler.class 設置爲 org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
- 隊列的放置:(1)specified 表明應用放進指定隊列中 (2)primaryGroup 應用放在以用戶的主Unix組名命名的隊列中 (3)Default 應用放進dev.eng隊列中
彈性隊列:單個隊列不會超過隊列容量,但不夠時會進行彈性擴容
延遲調度
搶佔:
- 開啓搶佔:yarn.scheduler.fair.preemption
- 最小共享:指定時間未獲得被承諾的最小共享資源,調度器就會搶佔其他容器
- 公平共享:指定時間內獲得的資源仍低於其公平共享份額的一半,調度器就會搶佔其他容器
第5章 Hadoop的I/O操作
HDFS數據完整性校驗
- Hdfs會對寫入的所有數據計算校驗和,並在讀取數據時驗證校驗和
- datanode負責在收到數據後存儲該數據及其校驗和之前對數據進行驗證
- 客戶端從datanode讀取數據時,也會驗證校驗和,將它們與datanode中存儲中存儲的校驗和進行比較。
- datanode後臺會運行DataBolockScanner,定期檢查datanode上的數據塊
(若不通過,namenode會標記損壞,並將副本複製到另一個datanode)
fs -checksum 檢驗校驗和
LocalFileSystem通過ChecksumFileSystem執行客戶端的校驗和驗證,在寫入文件時會產生.filename.crc隱藏文件
壓縮
在MapReduce中使用壓縮:mapreduce.output.fileoutputformat.compress = true
序列化
將結構化對象轉化爲字節流以便在網絡上傳輸或寫到磁盤進行永久存儲的過程
序列化兩大領域:進程間通訊 、 永久存儲
- Writable接口
- WritableComparable接口和comparator
Wriable類
Java基本類型 Writable實現
boolean BooleanWritable
byte ByteWritable
Short ShortWritable
int IntWritable 定長格式
VintWritable 變長格式
float FloatWritable
long LongWriable
VlongWritable
double DoubleWritable
byte[] BytesWritable
null NullWritable
String[]/enum[] ObjectWritable
Writable集合類:
ArrayWritable、ArrayPrimitiveWritable、TwoDArrayWritable、MapWritable、SortedMapWritable、EnumMapWritable
第6章 MapReduce應用開發
Configuraion: 如果資源按順序添加,後添加的屬性會覆蓋之前定義的屬性
Maven創建Eclipse配置文件,將項目導入到Eclipse:
mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true
作業調優檢查:
- mapper的數量
- reducer的數量
- combiner
- 中間值的壓縮
- 自定義序列
- 調成shuffle
MapReduce工作流
不同的mapper實現不同的函數,然後使用Hadoop的ChainMapper類庫將它們連接成一個mapper,結合使用ChainReducer,可以在MapReduce作業中運行一些列的mapper
管理MapReduce工作流:org.apache.hadoop.mapreduce.jobcontrol : JobControl
(表示一個作業的運行圖,可以加入作業配置,告知JobControl實例作業之間的依賴關係)
Apache Oozie:運行工作流系統,由相互依賴的作業組成,Oozie更容易對失敗流重運行,Oozie通過回調向客戶端通知工作流的狀態
- 工作流引擎:負責存儲和運行由不同類型Hadoop作業組成的工作流
- coordinator引擎:負責基於預定義的調度策略及數據可用性運行作業流作業
工作流:是一個由動作節點和控制流節點組成的DAG
工作流定義:XML P180
Hue可操作管理的組件包括:HDFS、Hive、Zookeeper、Oozie、MapReduce、Solr、HBase、Spark
第7章 MapReduce的工作機制
- 客戶端,提交MapReduce作業
- Yarn資源管理器,負責協調集羣上計算機資源的分配
- Yarn節點管理器,負責啓動和監視集羣中機器上的計算容器
- MapReduce的application master,負責協調運行MapReduce作業的任務。它和MapReduce任務在容器中運行,這些容器由節點管理器進行管理
- 分佈式文件系統(HDFS),用來與其他實體間共享作業文件
application master是一個java程序,主類是MRAppMaste,application master必須決定如果構成MapReduce作業的各個任務
Uber任務運行:小作業(少於10個mapper且只有一個reducer)選擇在同一個JVM上運行任務
開啓Uber:mapreduce.job.ubertask.enable = true
Reduce任務開始:直到5%的map任務完成,reduce請求才開始發出。Reduce任務能在集羣中任意位置運行,但是map任務的請求有着本地化侷限。
mapreduce.map.memory.mb
mapreduce.reduce.memory.mb
mapreduce.map.cpu.vcores
mapreduce.reduce.cpu.vcoresp.memory.mb
YarnChild : application master 通過與節點管理器通信來啓動容器,該任務由主類爲YarnChild的一個Java應用程序執行。它在運行前,首先將任務需要的資源本地化,包括作業的配置、jar文件和所有來自分佈式緩存的文件,最後,運行map任務和reduce任務。
子進程通信:子進程和自己的父application master 通過 umbilical 接口通信。
每隔3秒鐘,任務通過這個umbilical接口向自己的application master報告進度和狀態,application master會形成一個作業的匯聚視圖。
客戶端每秒輪詢一次application master接收最新狀態
- 任務失敗:application master被告知任務失敗後,將重新調度該任務的執行,並會試圖避免在以前失敗過的節點管理器上重新調度該任務,如果一個任務失敗過4次,將不會再嘗試。
map最多嘗試次數:mapreduce.map.maxattempts
reduce最多嘗試次數:mapreduce.reduce.maxattempts
允許任務失敗的百分比:
mapreduce.map.failures.maxpercent mapreduce.reduce.failures.maxpercent
- application master運行失敗:
mapreudce.am.max-attempts
- 節點管理器運行失敗:如果10分鐘內沒有收到一條心跳信息,資源管理器將會通知停止發送心跳信息的節點管理器,並且將其從自己的節點池中移除以調度啓動容器。如果應用程序的運行失敗次數過高,節點管理器可能會被拉黑
Shuffle和排序:
將map輸出作爲輸入傳給reducer的過程成爲shuffle,每個map任務都有一個環形內存緩衝區用於存儲任務輸出
combiner使得map輸出結果更緊湊,可以在輸入上反覆運行,不影響最終結果。
Reduce複製階段:每個map任務完成時間可能不同,在每個map完成時,reduce開始複製map的輸出。reduce有少量的複製線程,因此能夠並行取得map輸出。默認值是5個線程。(reducer中的一個線程會定期詢問master以便獲取map輸出主機的位置,直到獲取所有輸出位置)
- 如果map輸出相當小,會被複制到reduce任務的JVM內存中
- 否則map輸出被複制到磁盤
Reduce排序階段:複製完所有map輸出後,reduce任務進入排序階段,每個階段將合併map輸出,維持順序排序。
mapreduce.task.io.sort.factor 合併因子(如果設置爲10,每趟將合併10個文件)
Map端調優
mapreduce.task.io.sort.mb |
排序map輸出時使用的內存緩衝區的大小 |
mapreduce.map.sort.spill.percent |
map輸出內存緩衝和用來磁盤使用的比例 |
mapreduce.task.io.sort.factor |
排序文件時,一次最多合併的流數 |
mapreudce.map.combine.minspills |
運行combiner所需要的最少溢出文件數 |
mapreduce.map.output.compress |
是否壓縮map輸出 |
mapreduce.map.output.compress.codec |
用於map輸出的壓縮編解碼器 |
mapreduce.shuffle.max.threads |
每個節點管理器的工作線程數 |
Reduce端調優
mapreduce.reduce.shuffle.parallelcopies |
用於把map輸出複製到reducer的線程mapreduce.reduce.shuffle.maxfetchfailures 在聲明失敗前,reducer獲取一個map輸出所花的最大時間 |
mapreudce.task.io.sort.factor |
排序文件時一次最多合併的流的數量 |
mapreudce.reduce.shuffle.input.buffer.percent |
在shuffle的複製階段,分配給map輸出的緩衝區佔堆空間的百分比 |
mapreduce.reduce.shuffle.merge.percent |
map輸出緩衝區的閾值使用比例 |
mapreduce.reduce.merge.in.mem.threshold |
啓動合併輸出和磁盤溢出寫過程的map輸出的閾值數 |
mapreduce.reduce.input.buffer.percent |
在reduce過程中,在內存中保存map輸出的空間佔整個空間的比例 |
map端可以通過避免多次溢出寫磁盤來獲得最佳性能
reduce端,中間數據全部駐留在內存時,就能獲得最佳性能
推測執行:在一個任務運行比預期慢的時候,它會盡量檢測,並啓動另一個相同的任務作爲備份。僅僅只針對運行速度低於平均水平的那一部分。一個任務成功完成後,其他的重複任務都將結束。
mapreudce.map.speculative
mapreduce.reduce.speculative
推測執行的優缺點:推測執行的目的是減少作業執行時間,但是以犧牲集羣效率爲代價的,推測執行會減少整體的吞吐量。
第8章 MapReduce的類型與格式
設置中間類型的原因:Java的泛型機制有很多限制:類型擦除導致運行過程中類型信息並非一直可見,所以Hadoop不得不進行明確規定。
分區操作:默認的partitioner是HashPartitioner,對每條記錄的鍵值進行哈希操作以決定該記錄應該屬於哪個分區。每個分區由一個reduce任務處理,所以分區數等於作業的reudce數。
記錄屬於哪個分區的確定:鍵的哈希值與最大值按位與,並用分區數進行取摸操作
getSplits()計算分片,然後發送到application master,application masster使用其存儲位置信息來調度map任務。
map任務調用一個RecordReader來生成鍵-值對,然後傳遞給map函數
FileInputFormat類
- 用於指出文件位置
- 爲輸入文件生成分片的代碼實現
- 輸入路徑:addInputPath、addInputPaths、setInputPaths
如果需要排除特定文件,可以使用FileInputFormat的setInputPathFilter()方法設置過濾器
FileInputFormat默認會使用過濾器排除隱藏文件(“.”,"_"開頭)
- 輸出分片:FileInputFormat只分割大文件(超過HDFS塊的大小)
小文件和CombineFileInputFormat類
小文件的危害:(1)處理小文件將增加運行作業必需的尋址次數 (2)HDFS集羣中存儲大量的小文件會浪費namenode的內存
CombineFileInputFormat將多個文件打包到一個分片中,以便每個mapper可以處理更多的數據。使得map操作中處理的數據量與HDFS中文件的塊大小之間的耦合度降低。
保證文件不被切分的方法:
(1)增加最小分片的大小,將它設置成大於要處理的最大文件大小。
(2)使用FileInputFormat具體子類,並且重寫isSplitable()方法,把返回值設置爲false
mapper中的信息:
調用Mapper的Context對象上的getInputSplit()方法,當輸入源自FileInputFormat時,該方法返回的InputSplit可以被強制轉換爲一個FileSplit
文本輸入 / 輸出:
- TextInputFormat 、TextOutputFormat:鍵是字節偏移量、值是這行的內容
跨行問題:TextInputFormat的邏輯記錄是以行爲單位的,有可能某一行會跨文件塊存放
這意味着map會執行一些遠程的讀操作
超長行會表現爲一個超長行,會導致內存溢出的錯誤。通常將mapreduce.input.linerecordreader.line.maxlength設置爲用字節數表示的,在內存範圍內的值
- KeyValueTextInputFormat:使用分界符對行進行分割,鍵爲排在製表符之前的Text序列
例: line1 -> abc
line2 -> bcd
(line1,abc) (line2,bcd)
- NLineInputFormat:
以上兩種mapper輸入行數不同,如果希望mapper收到固定的行數的輸入,需要將NLineInputFormat作爲InputFormat使用,鍵是行字節偏移量,值是行本身。
N是mapper收到的輸入行數,由mapreduce.input.lineinputformat.linespermap屬性控制
- StreamXmlRecordReader:
用來處理XML文檔
把stream.recordreader.class屬性設置爲org.apache.hadoop.streaming.mapreduce.StreamXmlRecordReader
- SequenceFileInputFormat 、SequenceFileOutputFormat:處理二進制輸入
- SequenceFileAsTextInputFormat、SequenceFileAsBinaryOutputFormat
- SequenceFileAsBinaryInputFormat
- FixedLengthInputFormat:用於從文件中讀取固定寬度的二進制記錄
- 多個輸入:MultipleInputs MultipleInputs.addInputPath(......)
- 數據庫輸入、輸出:使用JDBC從關係型數據庫中讀取數據
- MapFileOutputFormat:把map文件作爲輸出
- 多輸出:MultipleOutputFormat:
將數據寫入到多個文件,允許每個reducer創建多個文件。
map命名格式:name-m-nnnnn (nnnnn:塊號)
reduce命名格式:name-r-nnnnn
public class PartitionByStationUsingMultipleOutputs extends Configured implements Tool{
static class StationMapper extends Mapper<LongWritable,Text,Text,Text>{
private NcdcRecordParser parser = new NcdcRecordParser();
@Override
protected void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException{
parser.parse(value);
context.write(new Text(parser.getStationId()),value);
}
}
static class MultipleOutputsReducer extends Reducer<Text,Text,NullWritable,Text>{
private MultipleOutputs<NullWritable,Text> multipleOutputs;
@Override
protected void setup(Context context) throws IOException,InterruptedException{
multipleOutputs = new MultipleOutputs<NullWritable,Text>(context);
}
@Override
public void reduce(Text key,Iterable<Text> values,Context context) throws IOException,InterruptedException{
for(Text value:values){
multipleOutputs.write(NullWritable.get(),value,key.toString());
}
}
@Override
protected void cleanup(Context context) throws IOException,InterruptedException{
mutipleOutputs.close();
}
}
@Override
public int run(String[] args) throws Exception{
Job job = JobBuilder.parseInputAndOutput(this,getConf(),args);
if(job == null){
return -1;
}
job.setMapperClass(StationMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setReducerClass(MultipleOutputsReducer.class);
job.setOutputKeyClass(NullWritable.class);
return job.waitForCompetion(true)?0:1;
}
}
第9章 MapReduce特性
- 計數器
- 數據集
- 排序和連接
計數器:收集作業統計信息的有效手段之一
Hadoop內置計數器:
- MapReduce任務計數器(TaskCounter)
- 文件系統計數器(FileSystemCounter)
- FileInputFormat計數器(FileInputFormatCounter)
- FileOutputFormat計數器(FileOutputFormatCounter)
- 作業計數器(JobCounter)
p245 - 247:任務計數器、作業計數器
public class MaxTemperatureWithCounters extends Configured implements Tool{
enum Temperature{
MISSING,
MALFORMED
}
static class MaxTemperatureMapperWithCounters extends Mapper<LongWritable,Text,Text,IntWritable>{
private NcdcRecordParser parser = new NcdcRecordParser();
@Override
protected void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException{
parser.parse(value);
if(parser.isValidTemperature()){
int airTemperature = parser.getAirTemperature();
context.write(new Text(parser.getYear()),new IntWritable(airTemperature));
}else if(parser.isMalformedTemperature()){
System.err.println("...")
context.getCounter(Temperature.MALFORMED).increment(1);
}else if(parser.isMissingTemperature()){
context.getCounter(Temperature.MISSING).increment(1);
}
//動態counter,不由枚舉定義的計數器
context.getCounter("TemperatureQuality",parser.getQuality()).increment(1);
}
}
}
//counters的獲取
Counters counters = job.getCounters();
counters.findCounter(MaxTemperatureWithCounters.Temperature.MISSING).getValue();
Hadoop內置採樣器
- InputSampler
InputSampler.Sampler<IntWritable,Text> sampler
= new InputSampler.RandomSampler<IntWritable,Text>(0.1,1000,10)
- IntervalSample 以一定間隔定期從分片中選擇鍵
- RandomSampler
分佈式緩存
及時將任務過程中的文件和存檔複製到任務節點以供使用,各個文件通常只需要複製到一個節點一次,將文件“本地化”。
當緩存容量超過一定範圍,根據最近最少使用的原則刪除文件以騰出空間。
-archives 向任務中複製存檔文件(jar)
-libjars 把jar文件添加到mapper和reducer任務的類路徑中
-files 分發文件
緩存API:
兩類對象:Files(Path)、Achives(URI)
- addCacheXXXX()
- setCacheXXXXs():一次性添加一組文件、存檔
- addXXXXToClassPath():將文件或存檔添加到MapReduce任務的類路徑
第10章 構建Hadoop集羣
Apache Ambari
一個集羣保存兩年的數據大致需要100臺機器
格式化HDFS:創建一個空的文件系統,創建初始版本的namenode(不涉及datanode)
hdfs namenode -format
start-dfs.sh的過程
- 在每臺機器上啓動一個namenode,這些機器由執行hdfs getconf -namenodes得到的返回值確定
- 在slaves文件列舉的每臺機器上啓動一個datanode
- 在每臺機器上啓動一個輔助namenode,這些機器由執行hdfs get conf -secondarynamenodes 得到的返回值所確定
start-yarn.sh的過程
- 在本地機器上啓動一個資源管理器(ResourceManager)
- 在slaves文件列舉的每臺機器上啓動一個節點管理器(NodeManager)
namenode目錄:dfs.namenode.name.dir
datanode目錄:dfs.datanode.data.dir
dfs檢查點:dfs.namenode.checkpoint.dir 指定一系列目錄來保存檢查點
緩衝區大小:io.file.buffer.size
塊大小:dfs.blocksize
datanode能夠使用存儲目錄上的所有閒置空間:dfs.datanode.du.reserved
回收站回收的時間:fs.trash.interval
HDFS會自動刪除回收站中的文件,但其他文件系統並不具備這項功能
執行以下命令可以刪除已在回收站中超過最小時限的所有文件:
hadoop fs -expunge
慢啓動Reduce:百分之多少的map完成纔開始reduce
mapreduce.job.reduce.slowstart.completedmaps
短迴路本地讀:dfs.client.read.shortcircuit = true
客戶端聯繫datanode,然後通過tcp連接發送給客戶端
如果正在讀取的數據塊和客戶端在同一個節點上,那麼客戶端繞過網絡從磁盤上直接讀取數據效率會更高
安全性:
Hadoop文件許可模塊只提供一種簡單的認證機制來決定各個用戶對特定文件的訪問權限
Kerberos:實現用戶認證,鑑定登錄帳號是否就是所聲稱的用戶
Hadoop:決定該用戶到底擁有多少權限
Kerberos:
- 認證:客戶端向認證服務端發送一條報文,並獲取一個含時間戳的票據授予票據(TGT)
TGT具有一定的有效期(10個小時)
- 授權:客戶端使用TGT向票據授予服務器,並請求一個服務票據(TGS)
- 服務請求:客戶端向服務器出示服務票據(TGS),以證實自己的合法性
認證服務器(TGT) + 票據服務器(TGS) = KDC (kerberos key distribution center)
通用的做法是自動認證:在登錄操作系統的時候自動執行認證操作,從而只需單次登錄到Hadoop
ktutil命令創建一個Kerberos的keytab文件
- 將coresite.xml文件中的hadoop.security.authentication 屬性設置爲true
- 啓動服務級別的授權,將同一文件中的hadoop.security.authorization屬性設置爲true
klist:命令查看票據的過期時間
kdestroy:指定可消毀票據
委託令牌:Hadoop使用委託令牌支持後續的認證訪問,避免多次訪問KDC,委託令牌的創建和使用過程均由Hadoop代表用戶透明地進行,因而用戶執行kinit命令登錄之後,無需再做額外的操作。
委託令牌由服務器創建(namenode),可以視爲客戶端和服務器之間共享的一個密文
默認hdfs實例會自動獲取委託令牌,但是如果訪問其他·hdfs集羣,mapreduce.job.hdfs-servers作業屬性設置爲一個逗號隔離開的HDFS URI列表,才能夠獲取相應的委託令牌。
Hadoop基準評測程序:
hadoop-mapreduce-client-jobclient-xx-tests.jar
hadoop-mapreudce-*-tests.jar
TeraSort:對輸入進行全排序
- 使用teragen生成隨機數據
hadoop jar $HADOOP_HOME/share/hadoop /mapreduce/hadoop-mapreduce-examples-*.jar
teragen -Dmapreduce.job.maps=1000 10t random-data
- 運行TeraSort
hadoop jar $HADOOP_HOME/share/hadoopmapreduce/hadoop-mapreudce-exmaples-*.jar terasort random-data sorted-data
- 驗證sorted-data文件中的數據是否已經排好序
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar teravalidate sorted-data report
- TestDFSIO : 測試I/O性能
- MRBench:多次運行小型作業,檢驗小型作業能否快速響應
- NNBench:測試namenode硬件的加載過程
- Gridmix:基準評測程序套裝
- SWIM:真實的MapReduce工作負載庫,用來測試負載
- TPCx-HS:基本TeraSort的標準基準測評程序
第11章 管理Hadoop
namenode目錄結構:
${dfs.namenode.name.dir} / dfs.namenode.name.dir描述了一組目錄,各個目錄存儲着鏡像內容
|---------- current
| |----------VERSION //Java屬性文件,包含着正在運行的HDFS的版本信息
| |----------edits_000001-0000019
| |----------edits_inprogress_000000070
| |----------fsimage_000000 //fsimage文件都是文件系統元數據的一個完整永久性檢查點
//如果namenode發生故障,最近的fsimage文件將被載入到內存以重構元數據的最近狀態
| |----------fsimage_000000.md5
| |----------fsimage_0000019
| |----------fsimage_0000019.md5
| |----------seen_txid
|------------ in_use.lock //文件鎖文件,namenode使用該文件對目錄進行加鎖
VERSION:
namespaceID :文件系統命名空間唯一標示符,在namenode首次格式化創建
clusterID:集羣整體賦予的標示符
cTime:namenode存儲系統創建時間
storageType:存儲目錄包含的namenode的數據結構
blockpoolID:數據池唯一標示符
layoutVersion:hdfs持久性數據結構的版本(與Hadoop版本無關)
- 編輯日誌在概念上是單個實體,在磁盤上體現爲多個文件。每個文件稱爲一個“段”,後綴edits及後綴組成,後綴是該文件包含的事務ID
- 任一時刻只有一個文件處於打開可寫狀態,在每個事務完成之後,且在向客戶端發送成功代碼之前,文件都需要更新和同步
- 當namenode向多個目錄寫數據時,只有在所有寫操作更新並同步到每個複本之後可返回成功代碼
主namenode,輔namenode(一般運行在另一個機器上)
- 輔助namenode請求主namenode停止使用正在進行中的edits文件,這樣新編輯記錄到一個新文件中。主namenode還會更新所有存儲目錄中的seen txid文件
- 輔助namenode從主namenode獲取最近的fsimage和edits文件
- 輔助namenode將fsimage文件載入內存,逐一執行edits文件中的事務,創建新的合併後的fsimage文件
- 輔助namenode將新的fsimage文件發送回主namenode,主namenode將其保存爲臨時的.ckpt文件
- 主namenode重新命名臨時的fsimage文件,便日後使用
安全模式創建檢查點:hdfs dfsadmin -saveNamespace
查看namenode是否處於安全模式:hdfs dfsadmin -safemode get
namenode進入安全模式:hdfs dfsadmin -safemode enter
退出安全模式:hdfs dfsadmin -safemode leave
執行某些命令前namenode退出安全模式:hdfs dfsadmin -safemode wait
創建檢查點的條件:
(1)dfs.namenode.checkpoint.period 檢查週期
(2)dfs.namenode.checkpoint.txns 事務文件的大小
輔助namenode發生故障時,輔助namenode恢復數據的方法:
(1)將相關存儲目錄複製到新的namenode
(2)使用-importCheckpoint選項啓動namenode守護進程,從而將輔助namenode用作新的主namenode
namenode啓動時,首先將文件(fsimage)載入內存中,並執行編輯日誌(edits)中的各項編輯操作。一旦在內存中成功建立文件系統元數據的映象,則創建一個新的fsimage文件和一個空的編輯日誌。
datanode目錄結構:
${dfs.datanode.data.dir}/
|- current
| |------BP-xxx-127.0.0.1-xxx
| | |---current
| | |---VERSION
| | |---finalized
| | | |---blk_xxxxx
//hdfs數據塊在以blk_爲前綴名的文件中,文件名包含了該文件存儲的塊原始字節數
| | | |---blk_xxxxx.meta //版本和類型信息、校驗和
| | | |---blk_yyyyy
| | | |---blk_yyyyy.meta
| | |---row
| |---VERSION
|-----in_use.lock
dfsadmin 工具:查看HDFS狀態信息,又可在HDFS上執行管理操作
fsck:檢查監控狀況,缺失或過多的塊
fsck只是從namenode獲取信息,並不與任何datanode進行交互,並不真正獲取塊數據
hdfs 查找文件的數據塊:hdfs fsck /user/tom/xxxx -files -blocks -racks
datanode塊掃描器
掃描並檢測塊(dfs.datanode.scan.period.hours )
均衡器
start-balancer.sh
將塊從忙碌的datanode移動到相對空閒的datanode,從而重新分配塊
均衡器會一直運行,知道集羣變得均衡爲止
度量(Metrics)和JMX
度量:度量爲管理員服務
計數器:主要爲MapReduce用戶服務
計數器:MapReduce確保計數器值由任務JVM產生,再傳回application master,最終傳回MapReduce作業的客戶端
度量:收集機制獨立於接收更新的組件
委任:擴大和縮小存儲容量
向集羣添加新節點的步驟如下:
1. 將新節點的網絡地址添加都include文件中
2. 運行以下指令,將審覈過的一系列datanode集合更新至namenode信息:
hdfs dfsadmin -refreshNodes
3. 將審覈過的一系列節點管理器信息更新到資源管理器:
yarn rmadmin -refreshNodes
4. 在以新節點更新slaves文件
5. 啓動新的datanode和節點管理器
向集羣解除舊節點的步驟如下:
用戶將擬退出的若干datanode告知namenode,Hadoop系統就可在這些datanode停機之前將塊複製到其他datanode
節點是否出現在include文件中 |
節點是否出現在exclude文件中 |
解釋 |
否 |
否 |
節點無法連接 |
否 |
是 |
節點無法連接 |
是 |
否 |
節點可連接 |
是 |
是 |
節點可連接,將被刪除 |
1. 將待解除節點的網絡地址添加到exclude文件中,不更新include文件
2. 使用一組新的審覈過的datanode來更新namenode設置:
hdfs dfsadmin -refreshNodes
3. 使用新的審覈過的節點管理器來更新資源管理器設置:
yarn rmadmin -refreshNodes
4. 從include文件中移除這些節點,並運行以下命令:
hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes
5. 從slaves文件中移除節點
Hadoop升級過程:
- 在執行升級任務之前,確保前一升級已經定妥
- 關閉yarn和mapreduce守護進程
- 關閉hdfs,並備份namenode目錄
- 在集羣和客戶端安裝新版本的hadoop
- 使用 -upgrade選項啓動hdfs
- 等待,直到升級完成
- 檢查hdfs是否運行正常
- 啓動yarn和mapreudce守護進程
- 回滾或定妥升級任務
啓動升級:start-dfs.sh -upgrade
等待、直到升級完成:hdfs dfsadmin -upgradeProgress status
回滾:stop-dfs.sh start-dfs.sh -rollback