NameNode、DataNode和MapReduce運行原理


一、Namenode
1.作用
①負責元數據的存儲
②負責接受和處理客戶端的請求
③負責接受DN上報的信息
④和DN保持心跳,向DN下達命令

2.元數據
包含兩部分
①文件的屬性(保存在edits+fsimage)
②塊的位置信息(由DN啟動后自動上報,動態生成)

3.存儲元數據的文件
①edits文件: NN啟動后,客戶端每次的寫操作都會記錄在edits文件中
②fsimage文件:
在NN第一次格式化時生成,在NN每次執行checkpoint,滿足條件后,會重新將內存中合並后的元數據
持久化到fsimage文件中

4.checkpoint
每次Namenode會定期進行checkpoint,主要了為了防止在運行期間產生大量的edits文件,導致下次重啟時
恢復時間過長!

定期將edits文件中新的內容,持久化到fsimage文件中,進行快照存儲!

默認的機制:
①沒間隔1h,執行一次
②距離上次,又新產生了100w次txns操作

5.NN的安全模式
NN的安全模式主要是為了接受DN上報塊信息!

每次NN啟動時,會自動進入安全模式!在安全模式只能有限讀,不能寫!

當DN上報的塊的最小副本數的總數 / 塊的總數 > 0.999時,NN會在30秒后自動離開!

手動操作: hdfs dfsadmin -safemode get|enter|leave|wait

二、SecondaryNamenode
如果配置了SecondaryNamenode,2nn會幫助NN進行checkpoint操作!

三、Datanode
1.作用
①接受客戶端的讀寫塊請求
②DN負責維護塊的完整性,通過定期檢查塊的校驗和判斷塊是否損壞
損壞的塊,DN會自動刪除,在下次啟動時,不會上報給NN
③DN負責定期向NN匯報塊的信息,接收NN的其他任務(復制塊等)

2.Datanode的掉線時長
DN和NN每間隔dfs.heartbeat.interval(3s)進行一次心跳!
如果DN和NN上一次心跳舉例當前時間,
已經過了2*dfs.namenode.heartbeat.recheck-interval(5min)+10*dfs.heartbeat.interval,
NN會將DN的狀態標記為DEAD!

四、其他配置
1.NN的多目錄配置
NN的多目錄指對元數據進行多個目錄的同時備份,通過hdfs-site.xml中的dfs.namenode.name.dir進行設置!

2.DN的多目錄配置
如果機器添加了新的磁盤,希望DN在寫入塊時,向新磁盤的目錄進行寫入!
配置DN的多目錄!
通過hdfs-site.xml中dfs.datanode.data.dir進行配置

3.服役新節點
①准備機器,安裝軟件,配置NN,RM的相關配置
②啟動datanode和nodemanager進程即可


服役了新的DN節點后,可以執行再平衡的命令,這個命令可以將集群中塊進行重新平衡分配!
./start-balancer.sh

4.白名單
白名單是為了阻止某個進程加入集群!
白名單之外的機器,無法進入集群!
白名單通過hdfs-site.xml中的dfs.hosts配置!
可以使用 hdfs dfsadmin -refreshNodes刷新配置,讀取此配置信息!

5.黑名單
退役datanode!
黑名單通過hdfs-site.xml中的dfs.hosts.exclude配置!
黑名單中的機器在最后一次啟動時,會將當前機器的塊移動到其他節點!
注意: 如果當前集群中在線的DN節點不滿足某些文件的副本數要求,當前退役節點是無法退役完成!

6.集群間的拷貝
hadoop distcp hdfs://xxxx:xxx/xxx hdfs://xxxx:xxx/xxx

7.在線歸檔
歸檔: hadoop arichieve -archievename 歸檔文件名 -p 父目錄 輸入文件... 輸出目錄
使用: hadoop fs -ls har:///歸檔文件名

在線歸檔不會刪除原文件!

五、MapReduce

 

二、MR的核心編程思想

1.概念
Job(作業) : 一個MR程序稱為一個Job
MRAppMaster(MR任務的主節點): 一個Job在運行時,會先啟動一個進程,這個進程為 MRAppMaster。
負責Job中執行狀態的監控,容錯,和RM申請資源,提交Task等!

Task(任務): Task是一個進程!負責某項計算!

Map(Map階段): Map是MapReduce程序運行的第一個階段!
Map階段的目的是將輸入的數據,進行切分。將一個大數據,切分為若干小部分!
切分后,每個部分稱為1片(split),每片數據會交給一個Task(進程)進行計算!

Task負責是Map階段程序的計算,稱為MapTask!

在一個MR程序的Map階段,會啟動N(取決於切片數)個MapTask。每個MapTask是並行運行!

Reduce(Reduce階段): Reduce是MapReduce程序運行的第二個階段(最后一個階段)!
Reduce階段的目的是將Map階段,每個MapTask計算后的結果進行合並匯總!得到最終結果!
Reduce階段是可選的!

Task負責是Reduce階段程序的計算,稱為ReduceTask!
一個Job可以通過設置,啟動N個ReduceTask,這些ReduceTask也是並行運行!
每個ReduceTask最終都會產生一個結果!

2.MapReduce中常用的組件
①Mapper: map階段核心的處理邏輯
②Reducer: reduce階段核心的處理邏輯
③InputFormat: 輸入格式
MR程序必須指定一個輸入目錄,一個輸出目錄!
InputFormat代表輸入目錄中文件的格式!
如果是普通文件,可以使用FileInputFormat.
如果是SequeceFile(hadoop提供的一種文件格式),可以使用SequnceFileInputFormat.
如果處理的數據在數據庫中,需要使用DBInputFormat

④RecordReader: 記錄讀取器
RecordReader負責從輸入格式中,讀取數據,讀取后封裝為一組記錄(k-v)!

⑤OutPutFormat: 輸出格式
OutPutFormat代表MR處理后的結果,要以什么樣的文件格式寫出!
將結果寫出到一個普通文件中,可以使用FileOutputFormat!
將結果寫出到數據庫中,可以使用DBOutPutFormat!
將結果寫出到SequeceFile中,可以使用SequnceFileOutputFormat
⑥RecordWriter: 記錄寫出器
RecordWriter將處理的結果以什么樣的格式,寫出到輸出文件中!

在MR中數據的流程:
①InputFormat調用RecordReader,從輸入目錄的文件中,讀取一組數據,封裝為keyin-valuein對象
②將封裝好的key-value,交給Mapper.map()------>將處理的結果寫出 keyout-valueout
③ReduceTask啟動Reducer,使用Reducer.reduce()處理Mapper寫出的keyout-valueout,
④OutPutFormat調用RecordWriter,將Reducer處理后的keyout-valueout寫出到文件

⑦Partitioner: 分區器
分區器,負責在Mapper將數據寫出時,將keyout-valueout,為每組keyout-valueout打上標記,進行分區!
目的: 一個ReduceTask只會處理一個分區的數據!

六、MapReduce的運行流程概述
需求: 統計/hello目錄中每個文件的單詞數量,
a-p開頭的單詞放入到一個結果文件中,
q-z開頭的單詞放入到一個結果文件中。

例如: /hello/a.txt 200M
hello,hi,hadoop
hive,hadoop,hive,
zoo,spark,wow
zoo,spark,wow
...
/hello/b.txt 100m
hello,hi,hadoop
zoo,spark,wow
...

1.Map階段(運行MapTask,將一個大的任務切分為若干小任務,處理輸出階段性的結果)
①切片(切分數據)
/hello/a.txt 200M
/hello/b.txt 100m

默認的切分策略是以文件為單位,以文件的塊大小(128M)為片大小進行切片!
split0:/hello/a.txt,0-128M
split1: /hello/a.txt,128M-200M
split2: /hello/b.txt,0M-100M

②運行MapTask(進程),每個MapTask負責一片數據
split0:/hello/a.txt,0-128M--------MapTask1
split1: /hello/a.txt,128M-200M--------MapTask2
split2: /hello/b.txt,0M-100M--------MapTask3

③讀取數據階段
在MR中,所有的數據必須封裝為key-value
MapTask1,2,3都會初始化一個InputFormat(默認TextInputFormat),每個InputFormat對象負責創建一個RecordReader(LineRecordReader)對象,
RecordReader負責從每個切片的數據中讀取數據,封裝為key-value.

LineRecordReader: 將文件中的每一行封裝為一個key(offset)-value(當前行的內容)
舉例:
hello,hi,hadoop----->(0,hello,hi,hadoop)
hive,hadoop,hive----->(20,hive,hadoop,hive)
zoo,spark,wow----->(30,zoo,spark,wow)
zoo,spark,wow----->(40,zoo,spark,wow)

④進入Mapper的map()階段
map()是Map階段的核心處理邏輯! 單詞統計! map()會循環調用,對輸入的每個Key-value都進行處理!
輸入:(0,hello,hi,hadoop)
輸出:(hello,1),(hi,1),(hadoop,1)

輸入:(20,hive,hadoop,hive)
輸出:(hive,1),(hadoop,1),(hive,1)

輸入:(30,zoo,spark,wow)
輸出:(zoo,1),(spark,1),(wow,1)

輸入:(40,zoo,spark,wow)
輸出:(zoo,1),(spark,1),(wow,1)

⑤目前,我們需要啟動兩個ReduceTask,生成兩個結果文件,需要將MapTask輸出的記錄進行分區(分組,分類)
在Mapper輸出后,調用Partitioner,對Mapper輸出的key-value進行分區,分區后也會排序(默認字典順序排序)
分區規則: a-p開頭的單詞放入到一個區
q-z開頭的單詞放入到另一個區
MapTask1:
0號區: (hadoop,1),(hadoop,1),(hello,1),(hi,1),(hive,1),(hive,1)
1號區: (spark,1),(spark,1),(wow,1) ,(wow,1),(zoo,1)(zoo,1)

MapTask2:
0號區: 。。。
1號區: ...


MapTask3:
0號區: (hadoop,1),(hello,1),(hi,1),
1號區: (spark,1),(wow,1),(zoo,1)

2.Reduce階段
①copy
ReduceTask啟動后,會啟動shuffle線程,從MapTask中拷貝相應分區的數據!

ReduceTask1: 只負責0號區
將三個MapTask,生成的0號區數據全部拷貝到ReduceTask所在的機器!
(hadoop,1),(hadoop,1),(hello,1),(hi,1),(hive,1),(hive,1)
(hadoop,1),(hello,1),(hi,1),


ReduceTask2: 只負責1號區
將三個MapTask,生成的1號區數據全部拷貝到ReduceTask所在的機器!
(spark,1),(spark,1),(wow,1) ,(wow,1),(zoo,1)(zoo,1)
(spark,1),(wow,1),(zoo,1)
②sort

ReduceTask1: 只負責0號區進行排序:
(hadoop,1),(hadoop,1),(hadoop,1),(hello,1),(hello,1),(hi,1),(hi,1),(hive,1),(hive,1)
ReduceTask2: 只負責1號區進行排序:
(spark,1),(spark,1),(spark,1),(wow,1) ,(wow,1),(wow,1),(zoo,1),(zoo,1)(zoo,1)

③reduce
ReduceTask1---->Reducer----->reduce(一次讀入一組數據)

何為一組數據: key相同的為一組數據
輸入: (hadoop,1),(hadoop,1),(hadoop,1)
輸出: (hadoop,3)

輸入: (hello,1),(hello,1)
輸出: (hello,2)

輸入: (hi,1),(hi,1)
輸出: (hi,2)

輸入:(hive,1),(hive,1)
輸出: (hive,2)

ReduceTask2---->Reducer----->reduce(一次讀入一組數據)

輸入: (spark,1),(spark,1),(spark,1)
輸出: (spark,3)

輸入: (wow,1) ,(wow,1),(wow,1)
輸出: (wow,3)

輸入:(zoo,1),(zoo,1)(zoo,1)
輸出: (zoo,3)

④調用OutPutFormat中的RecordWriter將Reducer輸出的記錄寫出
ReduceTask1---->OutPutFormat(默認TextOutPutFormat)------>RecordWriter(LineRecoreWriter)
LineRecoreWriter將一個key-value以一行寫出,key和alue之間使用\t分割
在輸出目錄中,生成文件part-r-0000
hadoop 3
hello 2
hi 2
hive 2

ReduceTask2---->OutPutFormat(默認TextOutPutFormat)------>RecordWriter(LineRecoreWriter)
LineRecoreWriter將一個key-value以一行寫出,key和alue之間使用\t分割
在輸出目錄中,生成文件part-r-0001
spark 3
wow 3
zoo 3


2.運行流程
Map------------------------Reduce階段
split(切片)----read(讀取數據,封裝為輸入的k-v)---map(Mapper.map())----sort(分區和排序)-----------------copy(拷貝分區數據)-------sort(合並且排序)-----reduce(合並)------write(寫出數據)

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM