目錄
Hadoop
分布式計算平台,同時也是一個生態圈
- hadoop 1.X HDFS+MapReducer+Common
- hadoop 2.X HDFS+MAP+Reducer+Common
- hadoop 3.X java7->java8,引入糾刪碼,重寫shell腳本,支持超過兩個NameNode,默認端口改變
HDFS
分布式文件存儲系統(可靠,高吞吐),利用目錄樹定位文件
- 可靠性-維護多個副本
- 擴展性-隨時增減服務器
- 高效性-task並行
- 容錯性-失敗的任務重新分配執行
- 適合一次寫入多次讀出
- 支持數據的追加,不支持隨機修改
HDFS組件
NameNode
- NameNode 存儲文件的元數據,位置信息
- 配置副本策略
- 管理數據塊映射信息
- 處理讀寫請求
DataNode
- DataNode 存儲文件的真實數據,並做數據校驗
- 一個數據塊在DN中會存儲數據本身,數據長度,檢驗和以及時間戳。同時DN啟動后會向NN進行注冊,后續每隔一小時向NN匯報數據塊信息,同時每三秒進行一次NN心跳並帶回NN指令,如果10分鍾沒有心跳信號,NN會認為該節點宕機。
- 在數據節點退役過程中推薦使用黑名單進行退役,辭職后會進行HDFS數據轉移。
SecondaryNameNode
- SecondaryNameNode 對NameNode做備份,但不能頂替NN提供服務
- 定期合並鏡像文件,編輯日志,推送給NN
- 可以恢復NN的數據(可能不完整)
Client
- Client切分上傳的文件
- 告知NN文件的位置信息,交互DN的讀寫數據
- 通過命令管理HDFS
HDFS文件的上傳與下載
- 上傳:客戶端通過HDFS對象向NameNode提交上傳請求,NN確定文件狀態以及父目錄是否存在,返回許可。隨后用戶上傳文件的第一個數據塊,請求NN返回DataNode,NN根據請求返回三個DN節點,用戶通過輸出流請求在一個DN上上傳數據(上傳的DN根據網絡拓撲計算決定),然后該DN會調用其他的DN節點將這個通信信道建立完成。三個節點逐級應答客戶端,客戶端向第一個DN節點上傳一個數據塊,以packet為單位,DN收到后先進行落盤處理,同時將該packet傳送給第二個DN節點然后再傳給第三個DN節點。當第一個塊傳輸完成后,第二個數據塊重復上面的動作,傳遞完成后關閉傳輸流,傳輸過程中,第一個DN節點會將packet放入一個應答隊列,待所有節點相應完成后表示上傳成功。
- 下載: 客戶端訪問HDFS對象,向NameNode請求下載某文件,NameNode返回文件的元數據信息,以及數據塊坐在的位置。客戶端得到信息后獲取文件輸入流,根據就近原則隨機原則隨機挑選一個DN節點獲取packet,客戶端收到后現在本地緩存,然后寫入目標文件。
NameNode與SecondaryNameNode的機制
- NN在啟動后會將fsimage和edits加載到內存里,格式化后則是創建。客戶端對HDFS進行操作后,NN先將操作記錄到日志中,然后再內存中進行操作,2NN向NN詢問是否CheckPoint,帶回指令。如果CheckPoint,NN會生成一個滾動的日志文件,一個磁盤中編輯日志的復制文件,將磁盤中的鏡像文件和復制好的編輯日志文件復制到2NN中,加載到2NN內存中合並成一個合並文件,返回到NN中,NN用重命名的方式覆蓋原文件。
- fsimage是HDFS文件系統中元數據的一個永久性檢查點
- edits存放HDFS文件系統中所有的更新操作
- CheckPoint觸發點為1小時或者edits執行了一百萬次操作。2NN在一分鍾內確認三次NN的操作次數
Yarn組件
- ResourceManager 處理客戶端請求,監控NodeManager,啟動ApplicationMaster,調度資源
- NodeManager 管理單個節點上的資源,處理ResourceManager的命令,處理ApplicationMaster的命令
- Contianer 封裝單個節點上的資源
- ApplicationMaster 負責數據切分,為應用申請資源,監控任務
MapReduce框架⭐
- 常用的數據序列化類型 String-》Text | Map-》MapWritable | Array-》ArrayWritable
- 一個運算程序一般是一個map階段和一個reduce階段,MapTask並發執行,互不相干。ReduceTask並發執行,依賴MapTask的數據結果。
- 關於進程,mrAppMaster負責過程調度和狀態協調,MapTask負責map階段的數據處理。ReduceTask負責reduce階段的數據處理。
MapReduce
Mapper與Reducer的繼承
- 繼承自Mapper並重寫map方法,讀取文件中內容並格式化輸出到Reduce中處理。
- 繼承自Reducer並重寫reduce方法,將map輸出的KV對接收處理后提交到job中執行。
Writable序列化接口
- Writable序列化接口是一個javaBean對象,其中封裝了需要系列化的參數。其中重寫的序列化與反序列化方法中的值順序必須一致。提供空參構造函數來實現反射調用。另外還需要重寫toString方法,令輸出數據可觀。
MapTask的工作機制(分而治之思想)
- 通過TextInputFormat組件(可自定義)將文件進行邏輯切片(HDFS是物理切塊),后續有多少個切片就會啟動多少個MapTask。其中每個切片大小與blok大小對應為128M。
- 文件切分完成后交給LineRecordReader按照換行符依次讀取數據交給定義的map方法。
- map方法輸出的KV對會進入一個環形緩沖區(內存區域),按照Key的HashCode值%NumReduceTask數量進行分區,環形緩沖區的默認大小是100M,達到80M后會進行溢寫,同時會進行分區內按照key執行快速排序,在最后一次溢寫結束后,會進行分區內的歸並排序,最后輸出一個文件給MapTask,文件中會有多個分區的索引來記錄偏移量。
MapTask的並行度
- 移動計算比移動數據划算、即寫滿blok大小防止出現數據的移動(數據本地化-HDFS的短路讀取)
- 單個數據切片大小為blok大小128M,最大超限10%,即129M也會分為一個切片。MapTask的並行度取決於split的數量。
ReduceTask的工作機制
- Copy階段,復制Map端輸出的一個分區的一片數據,對於同一個分區的數據,一定會進入同一個ReduceTask。在內存緩沖區中merge合並,溢出到磁盤的數據進行歸並排序合並。按照Key分組,調用一次Reduce方法。
ReduceTask的並行度
- ReduceTask的並行度通過job.setNumReduceTasks() 設置。0是與MapTask保持一致,不設置默認為一個。如果數據分配不均會產生數據傾斜的問題,即某個ReduceTask處理的數據量遠遠大於其他處理的數據量
Shuffle機制⭐
- Map階段處理后的數據傳給Reduce階段被稱為Shuffle,是MapReduce框架中最關鍵的一個流程。
- 數據分區,排序,分組,預聚合(combine),合並
- combiner使用的前提是不影響最終業務的邏輯。combiner是map方法后的執行流程,所以輸入輸出要和map保持一致
MR中的排序
- 部分排序:Hadoop的默認行為,MapReduce根據key排序,保證輸出文件內部有序。
- 全排序:喪失了MapReduce的並行功能,由一台機器處理全部文件,處理大型文件時效率極低,通過設置一個ReduceTask實現。
- 輔助排序:在Reduce端對接受的Key進行分組。
- 二次排序:自定義排序過程。
MR中文件的輸入和輸出
輸入
- TextInputFormat (普通文本文件,MR框架默認的讀取實現類型)
- KeyValueTextInputFormat(讀取一行文本數據按照指定分隔符,把數據封裝為kv類型)
- NLineInputF ormat(讀取數據按照行數進行划分分片)
- CombineTextInputFormat(合並小文件,避免啟動過多MapTask任務)
- CombineTextInputFormat切片原理
切片生成過程分為兩部分:虛擬存儲過程和切片過程
虛擬存儲過程:把輸入目錄下所有文件大小,依次和設置的setMaxInputSplitSize值進行比 較,如果不大於設置的最大值,邏輯上划分一個塊。如果輸入文件大於設置的最大值且大於 兩倍,那么以最大值切割一塊;當剩余數據大小超過設置的最大值且不大於最大值2倍,此時 將文件均分成2個虛擬存儲塊(防止出現太小切片)
切片過程:判斷虛擬存儲的文件大小是否大於setMaxInputSplitSize值,大於等於則單獨形成一個 切片。如果不大於則跟下一個虛擬存儲文件進行合並,共同形成一個切片。
例如四個小文件:1.txt -->2M ;2.txt-->7M;3.txt-->0.3M;4.txt--->8.2M,// 如果不設置InputFormat,它默認用的是TextInputFormat.class job.setInputFormatClass(CombineTextInputFormat.class);
//虛擬存儲切片最大值設置4m CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);
輸出
- 默認的輸出格式是TextOutputFormat,它把每條記錄寫為文本行。它的鍵和值可以是任意類型,
因為TextOutputFormat調用toString()方法把它們轉換為字符串。- 將SequenceFileOutputFormat輸出作為后續MapReduce任務的輸入,這是一種好的輸出格式,因為它的格式緊湊,很容易被壓縮。