前言
本篇篇幅較長,有許多集群搭建干貨,和枯燥乏味但是面試可能問到的理論知識(shí)。
思來想去不知道怎樣才能鼓勵(lì)自己加油學(xué)習(xí),想想要面對(duì)的生活還是假吧意思打開學(xué)習(xí)視頻吧。
目錄
一、引入
hdfs是什么
hdfs的由來
hdfs架構(gòu)體系
hdfs的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
缺點(diǎn)
二、HDFS_block簡介和注意事項(xiàng)
Block拆分標(biāo)準(zhǔn)
三、HDFS_block安全與管理
Block數(shù)據(jù)安全
Block?的管理效率
四、HDFS_Hadoop3完全分布式集群的搭建
1.集群的網(wǎng)絡(luò)和節(jié)點(diǎn)規(guī)劃
網(wǎng)絡(luò)規(guī)劃
節(jié)點(diǎn)規(guī)劃
2.Hadoop下載與安裝
3.配置Hadoop集群
配置環(huán)境變量
配置分布式集群環(huán)境
分發(fā)Hadoop集群安裝目錄及文件
啟動(dòng)和停止Hadoop集群
驗(yàn)證
Web端訪問
4.時(shí)間同步
安裝NTP服務(wù)器
配置其他機(jī)器的時(shí)間同步
五、HDFS_文件數(shù)據(jù)類型和啟動(dòng)檢查腳本編寫
文件數(shù)據(jù)類型
啟動(dòng)檢查腳本編寫
六、HDFS_NameNode(NN)
功能
性能
七、HDFS_DataNode(DN)
功能
八、HDFS_SNN與測試
SecondaryNameNode
傳統(tǒng)解決方案
SNN解決方案
SecondaryNameNode測試
SNN數(shù)據(jù)恢復(fù)
九、HDFS_安全模式和權(quán)限
安全模式
權(quán)限
十、HDFS_機(jī)架感知與副本存放策略
節(jié)點(diǎn)距離
機(jī)架感知
十一、HDFS_數(shù)據(jù)寫流程
宏觀過程
微觀過程
十二、HDFS_數(shù)據(jù)讀流程
十三、Hadoop1?的困境
十四、HDFS_高可用Hadoop-HA
設(shè)計(jì)思想
ANN
SNN
DataNode(DN)
QJM
ZKFC
Zookeeper
十五、HDFS_高可用腦裂
腦裂?brain-split
十六、HDFS_水平擴(kuò)展聯(lián)邦機(jī)制
為什么需要聯(lián)邦
Federation 架構(gòu)設(shè)計(jì)
HDFS Federation 的不足
十七、HDFS_HA搭建
初始化
角色分配
配置文件
啟動(dòng)
十八、HDFS_java訪問hdfs集群
HDFS的Java訪問接口
Java訪問HDFS主要編程步驟
使用FileSystem API讀取數(shù)據(jù)文件
編程實(shí)現(xiàn)
環(huán)境介紹
代碼實(shí)操
十九、HDFS_IDEA插件訪問hdfs集群
安裝插件
使用
結(jié)語
參考資料
一、引入
hdfs是什么
hdfs即Hadoop分布式文件系統(tǒng),是指被設(shè)計(jì)成適合運(yùn)行在通用硬件(commodity hardware)上的分布式文件系統(tǒng)(Distributed File System)。
它和現(xiàn)有的分布式文件系統(tǒng)有很多共同點(diǎn)。但同時(shí),它和其他的分布式文件系統(tǒng)的區(qū)別也是很明顯的。HDFS是一個(gè)高度容錯(cuò)性的系統(tǒng),適合部署在廉價(jià)的機(jī)器上。HDFS能提供高吞吐量的數(shù)據(jù)訪問,非常適合大規(guī)模數(shù)據(jù)集上的應(yīng)用。HDFS放寬了一部分POSIX約束,來實(shí)現(xiàn)流式讀取文件系統(tǒng)數(shù)據(jù)的目的。HDFS在最開始是作為Apache Nutch搜索引擎項(xiàng)目的基礎(chǔ)架構(gòu)而開發(fā)的。HDFS是Apache Hadoop Core項(xiàng)目的一部分。
hdfs的由來
隨著數(shù)據(jù)量越來越大,在一個(gè)操作系統(tǒng)存不下所有的數(shù)據(jù),那么就分配到更到的操作系統(tǒng)管理的磁盤中,但是管理不方便和維護(hù),迫切需要一種系統(tǒng)來管理多臺(tái)機(jī)器上的文件,這就是分布式文件管理系統(tǒng)(DFS),它能夠統(tǒng)一協(xié)調(diào)各個(gè)地理位置不同的機(jī)器拆分存儲(chǔ)文件或合并聚合文件。而HDFS只是DFS中的一種。
文件切分思想
源文件直接存放在一個(gè)磁盤上效率肯定很低
- 讀取效率低
- 如果文件太大會(huì)超出單機(jī)存儲(chǔ)的范圍
字節(jié)數(shù)組
- 文件在磁盤上真實(shí)存儲(chǔ)文件的抽象概念
- 數(shù)組可以進(jìn)行拆分合并,源文件不會(huì)收到影響
切分?jǐn)?shù)據(jù)
- 對(duì)數(shù)組進(jìn)行拆分
拼接數(shù)據(jù)
- 按照數(shù)組偏移量將字節(jié)數(shù)組拼接到一起
偏移量
- 當(dāng)前數(shù)據(jù)在數(shù)組中的相對(duì)位置,可以理解為下標(biāo)
- 數(shù)組都有對(duì)應(yīng)的下標(biāo),可以快速的定位數(shù)據(jù)
數(shù)據(jù)存儲(chǔ)原理
- 不管文件的的大小,所有的文件都是由字節(jié)數(shù)組構(gòu)成
- 如果我們要切分文件 , 就是將一個(gè)字節(jié)數(shù)組分成多份
- 我們將切分后的數(shù)據(jù)拼接到一起,數(shù)據(jù)可以繼續(xù)使用
- 我們需要根據(jù)數(shù)據(jù)的偏移量將他們重新拼接到一起
hdfs架構(gòu)體系
HDFS采用了主從(Master/Slave)結(jié)構(gòu)模型,一個(gè)HDFS集群是由一個(gè)NameNode和若干個(gè)DataNode組成的。其中NameNode作為主服務(wù)器,管理文件系統(tǒng)的命名空間和客戶端對(duì)文件的訪問操作;集群中的DataNode管理存儲(chǔ)的數(shù)據(jù)。
hdfs的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
高容錯(cuò)性
- 數(shù)據(jù)自動(dòng)保存多個(gè)副本。它通過增加副本的形式,提高容錯(cuò)性
- 某一個(gè)副本丟失以后,它可以自動(dòng)恢復(fù),這是由 HDFS?內(nèi)部機(jī)制實(shí)現(xiàn)的,我們不必關(guān)心
適合批處理
- 它是通過移動(dòng)計(jì)算而不是移動(dòng)數(shù)據(jù)
- 它會(huì)把數(shù)據(jù)位置暴露給計(jì)算框架
適合大數(shù)據(jù)處理
- 數(shù)據(jù)規(guī)模:能夠處理數(shù)據(jù)規(guī)模達(dá)到 GB、TB、甚至PB級(jí)別的數(shù)據(jù)
- 文件規(guī)模:能夠處理百萬規(guī)模以上的文件數(shù)量,數(shù)量相當(dāng)之大
- 節(jié)點(diǎn)規(guī)模:能夠處理10K節(jié)點(diǎn)的規(guī)模
流式數(shù)據(jù)訪問
- 一次寫入,多次讀取,不能修改,只能追加
- 它能保證數(shù)據(jù)的一致性
可構(gòu)建在廉價(jià)機(jī)器上
- 它通過多副本機(jī)制,提高可靠性
- 它提供了容錯(cuò)和恢復(fù)機(jī)制。比如某一個(gè)副本丟失,可以通過其它副本來恢復(fù)
缺點(diǎn)
不適合低延時(shí)數(shù)據(jù)訪問;
- 比如毫秒級(jí)的來存儲(chǔ)數(shù)據(jù),這是不行的,它做不到
- 它適合高吞吐率的場景,就是在某一時(shí)間內(nèi)寫入大量的數(shù)據(jù)。但是它在低延時(shí)的情況 ?下是不行的,比如毫秒級(jí)以內(nèi)讀取數(shù)據(jù),這樣它是很難做到的
無法高效的對(duì)大量小文件進(jìn)行存儲(chǔ)
- 存儲(chǔ)大量小文件的話,它會(huì)占用 ?NameNode大量的內(nèi)存來存儲(chǔ)文件、目錄和塊信息。這樣是不可取的,因?yàn)镹ameNode的內(nèi)存總是有限的
- 小文件存儲(chǔ)的尋道時(shí)間會(huì)超過讀取時(shí)間,它違反了HDFS的設(shè)計(jì)目標(biāo)
并發(fā)寫入、文件隨機(jī)修改
- ?一個(gè)文件只能有一個(gè)寫,不允許多個(gè)線程同時(shí)寫
- 僅支持?jǐn)?shù)據(jù) append(追加),不支持文件的隨機(jī)修改
二、HDFS_block簡介和注意事項(xiàng)
Block拆分標(biāo)準(zhǔn)
拆分的數(shù)據(jù)快需要等大
- 數(shù)據(jù)計(jì)算的時(shí)候簡化問題的復(fù)雜度
- 進(jìn)行分布式算法設(shè)計(jì)的時(shí)候,數(shù)據(jù)不統(tǒng)一,算法很難設(shè)計(jì)
- 數(shù)據(jù)拉取的時(shí)候時(shí)間相對(duì)一致
- 通過偏移量就知道這個(gè)塊的位置
- 相同文件,分成的數(shù)據(jù)塊大小應(yīng)該相等
數(shù)據(jù)塊 Block
- 數(shù)據(jù)被切分后的一個(gè)整體稱之為塊
- 在 H1 默認(rèn)大小為 64M, 在 H2 及其以后默認(rèn)大小為 128M
- 同一個(gè)文件中,每個(gè)數(shù)據(jù)塊大小要一致除了最后一個(gè)節(jié)點(diǎn)外
- 不同文件中,塊的大小可以不一致
- 文件大小不同可以設(shè)置不同的塊的數(shù)量
- 真實(shí)情況下,會(huì)根據(jù)文件大小和集群節(jié)點(diǎn)的數(shù)量綜合考慮塊的大小
- 數(shù)據(jù)塊的個(gè)數(shù) =Ceil (文件大小 / 每個(gè)塊的大?。?/li>
注意事項(xiàng)
- HDFS 中一旦文件被存儲(chǔ),數(shù)據(jù)不允許被修改
- 修改會(huì)影響偏移量
- 修改會(huì)導(dǎo)致數(shù)據(jù)傾斜
- 修改數(shù)據(jù)會(huì)導(dǎo)致蝴蝶效益
- 但是可以被追加,但是不推薦
- 追加設(shè)置需要手動(dòng)打開
- 一般 HDFS 存儲(chǔ)的都是歷史數(shù)據(jù)。所以 將來 Hadoop 的 mr 都用來進(jìn)行離線數(shù)據(jù)的處理
- 塊的大小一旦文件上傳之后就不允許被修改(128m -512M)
如果數(shù)據(jù)文件的切割點(diǎn)正好是一個(gè)單詞的中間部分,切分?jǐn)?shù)據(jù)如何保證數(shù)據(jù)的完整性??
三、HDFS_block安全與管理
Block數(shù)據(jù)安全
- 肯定要對(duì)存儲(chǔ)數(shù)據(jù)做備份
- 備份的數(shù)據(jù)肯定不能存放在一個(gè)節(jié)點(diǎn)上
- 使用數(shù)據(jù)的時(shí)候可以就近獲取數(shù)據(jù)
- 所以備份的數(shù)量要小于等于節(jié)點(diǎn)的數(shù)量
- 每個(gè)數(shù)據(jù)塊會(huì)有 3 個(gè)副本,相同副本是不會(huì)存放在同一個(gè)節(jié)點(diǎn)上
- 副本的數(shù)量可以變更
- 可能近期的數(shù)據(jù)被分析的可能性跟大,副本數(shù)可以多設(shè)置幾個(gè)
- 后期數(shù)據(jù)很少被分析,可以減少副本數(shù)
Block?的管理效率
需要專門給節(jié)點(diǎn)進(jìn)行分工
-
存儲(chǔ)?DataNode
- Slave,NameNode 下達(dá)命令,DataNode 執(zhí)行實(shí)際的操作
- 存儲(chǔ)實(shí)際的數(shù)據(jù)塊
- 執(zhí)行數(shù)據(jù)塊的讀/寫操作
-
記錄?NameNode
- master,一個(gè)管理者,不實(shí)際存儲(chǔ)數(shù)據(jù)
- 管理 HDFS 的名稱空間,維護(hù)著文件系統(tǒng)樹以及整個(gè)樹的所有文件和目錄(fsimage+edits)
- 管理數(shù)據(jù)塊(Block)映射信息
- 配置副本策略
- 處理客戶端讀寫請(qǐng)求
-
日志?secondaryNameNode
- 輔助NameNode,分擔(dān)其工作量
- 定期合并fsimage和edits,并推送給NameNode,緊急情況下,可輔助恢復(fù)NameNode
四、HDFS_Hadoop3完全分布式集群的搭建
注:前提是完成大數(shù)據(jù)學(xué)前準(zhǔn)備--zookeeper詳解與集群搭建(保姆級(jí)教程),這里重復(fù)操作將不再演示。
1.集群的網(wǎng)絡(luò)和節(jié)點(diǎn)規(guī)劃
網(wǎng)絡(luò)規(guī)劃
主機(jī)名 | IP地址 | 節(jié)點(diǎn)類型 |
node001 | 192.168.1.101 | master |
node002 | 192.168.1.102 | slave1 |
node003 | 192.168.1.103 | slave2 |
節(jié)點(diǎn)規(guī)劃
主機(jī)/服務(wù) | NameNode | SecondaryNameNode | DataNode | ResourceManager | NodeManager |
node001 | ?√ | ? √ | ? √ | ?√ | |
node002 | √ | ? √ | ? ?√ | ||
node003 | ? ?√ | ? ? √ |
2.Hadoop下載與安裝
- 官網(wǎng):官網(wǎng)下載
- 舊版本下載(官方的archive地址):舊版本下載,示例版本可在這里下載
- 清華大學(xué)開源軟件鏡像站下載(速度較快,只有新版本):清華大學(xué)開源軟件鏡像站
本次以hadoop-3.1.2.tar.gz為例搭建集群。
上傳hadoop-3.1.2.tar.gz到node001;
執(zhí)行解壓命令:tar -zxvf hadoop-3.1.2.tar.gz -C /opt/hadoop-3.1.2
3.配置Hadoop集群
配置環(huán)境變量
終端輸入:vim /etc/profile
末行加入:
export HADOOP_HOME=/opt/hadoop-3.1.2
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
配置分布式集群環(huán)境
對(duì)于Hadoop分布式集群模式的部署,常常需要配置的文件:
- 環(huán)境變量配置文件:hadoop-env.sh、yarn-env.sh、mapred-env.sh
- 全局核心配置文件:core-site.xml
- HDFS配置文件:hdfs-site.xml
- YARN配置文件:yarn-site.xml
- MapReduce配置文件:mapred-site.xml、slaves
hadoop-env.sh配置
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/hadoop-env.sh
末行加入:
export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root
注意:yarn-env.sh
、mapred-env.sh
兩個(gè)文件可以不用配置,如果要配置,可以在首次出現(xiàn)“export JAVA_HOME=……”
處配置為“export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64”
core-site.xml配置
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/core-site.xml
加入:
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node001:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/bdp/hadoop/full</value>
</property>
</configuration>
參數(shù)說明:
fs.defaultFS:該參數(shù)是配置指定HDFS的通信地址。其值為hdfs://node001:9000,9000為端口號(hào)。
hadoop.tmp.dir:該參數(shù)配置的是Hadoop臨時(shí)目錄,即指定Hadoop運(yùn)行時(shí)產(chǎn)生文件的存儲(chǔ)路徑,其值可以自行設(shè)置,不能設(shè)置為/tmp(/tmp是Linux的臨時(shí)目錄)。
注意:如果在普通用戶配置臨時(shí)目錄/var/bdp/hadoop/full,需要手動(dòng)創(chuàng)建及修改權(quán)限。
hdfs-site.xml配置
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/hdfs-site.xml
加入:
<configuration>
<property>
<name>dfs.namenode.http-address</name>
<value>node001:50070</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node002:50090</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/opt/hadoopTmp/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/opt/hadoopTmp/dfs/data</value>
</property>
</configuration>
參數(shù)說明:
dfs.namenode.http-address:該參數(shù)是配置NameNode的http訪問地址和端口號(hào)。因?yàn)樵诩阂?guī)劃中指定node001設(shè)為NameNode的服務(wù)器,故設(shè)置為node001:50070。
dfs.namenode.secondary.http-address:該參數(shù)是配置SecondaryNameNode的http訪問地址和端口號(hào)。在集群規(guī)劃中指定node002設(shè)為SecondaryNameNode的服務(wù)器,故設(shè)置為node002:50090。
dfs.replication:該參數(shù)是配置HDFS副本數(shù)量。
dfs.namenode.name.dir:該參數(shù)是設(shè)置NameNode存放的路徑。
dfs.datanode.data.dir:該參數(shù)是設(shè)置DataNode存放的路徑。
yarn-site.xml配置(這里可以暫時(shí)不配置,將在yarn篇專門介紹)
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/yarn-site.xml
<configuration>
<property>
<name>yarn.resourcemanager.hostsname</name>
<value>node001</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>node001:8088</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>106800</value>
</property>
<property>
<name>yarn.nodemanager.remote-app-log-dir</name>
<value>/user/container/logs</value>
</property>
</configuration>
參數(shù)說明:
yarn.resourcemanager.hostsname:該參數(shù)是指定ResourceManager運(yùn)行在那個(gè)節(jié)點(diǎn)上。
yarn.resourcemanager.webapp.address:該參數(shù)是指定ResourceManager服務(wù)器的web地址和端口。
yarn.nodemanager,aux-services:該參數(shù)是指定NodeManager啟動(dòng)時(shí)加載server的方式。
yarn.nodemanager.aux-services.mapreduce.shuffle.class:該參數(shù)是指定使用mapreduce_shuffle中的類。
yarn.log-aggregation-enable:該參數(shù)是配置是否啟用日志聚集功能。
yarn.log-aggregation.retain-seconds:該參數(shù)是配置聚集的日志在HDFS上保存的最長時(shí)間。
yarn.nodemanager.remote-app-log-dir:該參數(shù)是指定日志聚合目錄。
mapred-site.xml配置
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/mapred-site.xml
加入:
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>node003:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node003:19888</value>
</property>
<property>
<name>mapreduce.jobhistory.intermediate-done-dir</name>
<value>${hadoop.tmp.dir}/mr-history/tmp</value>
</property>
<property>
<name>mapreduce.jobhistory.done-dir</name>
<value>${hadoop.tmp.dir}/mr-history/done</value>
</property>
</configuration>
參數(shù)說明:
mapreduce.framework.name:該參數(shù)是指定MapReduce框架運(yùn)行在YARN上。
mapreduce.jobhistory.address:該參數(shù)是設(shè)置MapReduce的歷史服務(wù)器安裝的位置及端口號(hào)。
mapreduce.jobhistory.webapp.address:該參數(shù)是設(shè)置歷史服務(wù)器的web頁面地址和端口。
mapreduce.jobhistory.intermediate-done-dir:該參數(shù)是設(shè)置存放日志文件的臨時(shí)目錄。
mapreduce.jobhistory.done-dir:該參數(shù)是設(shè)置存放運(yùn)行日志文件的最終目錄。
slaves配置
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/slaves
添加所有節(jié)點(diǎn)主機(jī)名:
node001
node002
node003
分發(fā)Hadoop集群安裝目錄及文件
將處理好的hadoop-3.1.2分發(fā)到node002和node003(時(shí)間有些許長~)
分發(fā)到node002:scp -r /opt/hadoop-3.1.2 root@node002:/opt/
分發(fā)到node003:scp -r /opt/hadoop-3.1.2 root@node003:/opt/
啟動(dòng)和停止Hadoop集群
在啟動(dòng)hadoop集群前,需要先格式化NameNode,在Master主機(jī)下操作:
格式化命令:hdfs namenode -format? ? ? ?或者:hadoop namenode -format
格式化后即可
格式化后即可啟動(dòng)集群的節(jié)點(diǎn),可以分別啟動(dòng)HDFS和YARN,也可以一起啟動(dòng):
全部啟動(dòng)命令:
start-all.sh
如果啟動(dòng)報(bào)錯(cuò):node001: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
請(qǐng)參考《搭建hadoop報(bào)錯(cuò)》進(jìn)行改錯(cuò)
啟動(dòng)和停止HDFS:
????????start-dfs.sh ? ? ? ?#啟動(dòng)HDFS
????????stop-dfs.sh ? ? ? ?#停止HDFS啟動(dòng)和停止YARN:
????????start-yarn.sh ? ? ? #啟動(dòng)YARN
????????stop-yarn.sh ? ? ? #停止YARN全部啟動(dòng)和停止:
????????start-all.sh ? ? ? ?#啟動(dòng)HDFS和YARN
????????stop-all.sh ? ? ? ?#停止HDFS和YARN啟動(dòng)和停止歷史(日志)服務(wù)器:
????????mr-jobhistory-daemon.sh start historyserver ? ? #啟動(dòng)historyserver
????????mr-jobhistory-daemon.sh start historyserver ? ? #停止historyserver
驗(yàn)證
命令:jps
成功開啟后,會(huì)看到下圖所示的節(jié)點(diǎn)顯示:
Master: NameNode、DataNode、ResourceManager、NodeManager
slave1: SecondaryNameNode、DataNode、NodeManager
slave2: DataNode、NodeManager
Web端訪問
關(guān)閉防火墻:
service iptables stop
訪問HDFS:50070192.168.1.101:50070 ? ?#訪問HDFS,50070是端口
訪問YARN:8088192.168.1.101:8088 ? ? #訪問YARN,8088是端口
注意:根據(jù)自己配置的IP地址查看,必須關(guān)閉虛擬機(jī)里的防火墻,不然訪問不了。
到這,HDFS完全分布式集群搭建完畢!?
集群常用命令如下:
hdfs dfs -ls xxx
hdfs dfs -mkdir -p /xxx/xxx
hdfs dfs -cat xxx
hdfs dfs -put local cluster
hdfs dfs -get cluster local
hdfs dfs -cp /xxx/xxx /xxx/xxx
hdfs dfs -chmod -R 777 /xxx
hdfs dfs -chown -R zyh:zyh /xxx
4.時(shí)間同步
Hadoop集群對(duì)時(shí)間要求非常高,主節(jié)點(diǎn)與各從節(jié)點(diǎn)的時(shí)間都必須同步。NTP使用來使計(jì)算機(jī)時(shí)間同步的一種協(xié)議。配置時(shí)間同步服務(wù)器(NTP服務(wù)器)主要就是為了進(jìn)行集群的時(shí)間同步。
這里主要以node001作為NTP服務(wù)器,從節(jié)點(diǎn)node002和node003每10分鐘跟node001同步一次。
安裝NTP服務(wù)器
1 安裝配置NTP服務(wù)器
查看是否安裝NTP服務(wù),如果出現(xiàn)
ntp-x.x.x
和ntpdate-x.x.x
則不需要再安裝????????rpm -qa | grep ntp
安裝命令:
????????yum install -y ntp ? ? ?# 使用yum在線安裝
2 修改配置文件
ntp.conf
????????vim /etc/ntp.conf
① 啟用restrice,修改網(wǎng)段
打開restrice的注釋(刪除前面的#號(hào)),修改為自己的網(wǎng)段
② 注釋掉四行server域名,再添加兩行:
server 127.127.1.0 fudge 127.127.1.0 stratum 10
如圖所示:
?
③ 修改配置文件ntpd
命令:
vim /etc/sysconfig/ntpd
在此文件內(nèi),添加一行
SYNC_HWCLOCK=yes
,將同步后的時(shí)間寫入CMOS里。
④ 啟動(dòng)NTP服務(wù)
????????service ntpd start ? ? ?# 啟動(dòng)NTP服務(wù)
????????chkconfig ntpd on ? ? # 開機(jī)自啟動(dòng),永久啟動(dòng)兩個(gè)命令可以連用:service ntpd start &?chkconfig ntpd on
配置其他機(jī)器的時(shí)間同步
首先要保證從節(jié)點(diǎn)(其他機(jī)器)安裝有NTP,然后開始配置從節(jié)點(diǎn)跟主節(jié)點(diǎn)同步時(shí)間。以下操作是在node002和node003機(jī)器上配置(剩下的這兩臺(tái)都要配置):
① 注釋掉四行server域名配置,其后添加一行:
server node001
????????vim /etc/ntp.conf
?② 修改配置文件ntpd,此操作和前面的NTP服務(wù)器中配置一樣
????vim /etc/sysconfig/ntpd
添加一行
SYNC_HWCLOCK=yes
?③ 啟動(dòng)時(shí)間同步
啟動(dòng)NTP服務(wù):
service ntpd start & chkconfig ntpd on
也可以執(zhí)行命令:
ntpdate node001
完成同步node003節(jié)點(diǎn)與node002操作一致,不再演示。
最后通過:date '+%Y-%m-%d %H:%M:%S'? ? 測試三個(gè)節(jié)點(diǎn)時(shí)間是否一致。
五、HDFS_文件數(shù)據(jù)類型和啟動(dòng)檢查腳本編寫
文件數(shù)據(jù)類型
文件有一個(gè)stat命令
?? ?數(shù)據(jù)信息-->描述文件的屬性
文件有一個(gè)vim命令
分類
?? ???????元數(shù)據(jù)
????查看文件的數(shù)據(jù)信息
? ? File 文件名
?? ?Size 文件大小(字節(jié))
?? ?Blocks 文件使用的數(shù)據(jù)塊總數(shù)
?? ?IO Block 數(shù)據(jù)塊的大小
?? ?regular file:文件類型(常規(guī)文件)
?? ?Device 設(shè)備編號(hào)
?? ?Inode 文件所在的Inode
?? ?Links 硬鏈接次數(shù)
?? ?Access 權(quán)限
?? ?Uid 屬主id/用戶
?? ?Gid 屬組id/組名
?? ?Access Time:簡寫為atime,表示文件的訪問時(shí)間。當(dāng)文件內(nèi)容被訪問時(shí),更新這個(gè)時(shí)間
?? ?Modify Time:簡寫為mtime,表示文件內(nèi)容的修改時(shí)間。當(dāng)文件的數(shù)據(jù)內(nèi)容被修改時(shí),更新這個(gè)時(shí)間
?? ?Change Time:簡寫為ctime,表示文件的狀態(tài)時(shí)間,當(dāng)文件的狀態(tài)被修改時(shí),更新這個(gè)時(shí)間。例如文件的鏈接數(shù),大小,權(quán)限,Blocks數(shù)
啟動(dòng)檢查腳本編寫
終端輸入:vim start-bdp.sh
加入:
#!/bin/bash
echo "$(date)======啟動(dòng)node001的zookeeper========" >> /root/logs/start-bdp.log
zkServer.sh start >> /root/logs/start-bdp.log
echo "$(date)======啟動(dòng)node002的zookeeper========" >> /root/logs/start-bdp.log
ssh root@node002 "/opt/zookeeper-3.4.5/bin/zkServer.sh start" >> /root/logs/start-bdp.log
echo "$(date)======啟動(dòng)node003的zookeeper========" >> /root/logs/start-bdp.log
ssh root@node003 "/opt/zookeeper-3.4.5/bin/zkServer.sh start" >> /root/logs/start-bdp.log
echo " " >> /root/logs/start-bdp.log
echo " " >> /root/logs/start-bdp.log
echo " " >> /root/logs/start-bdp.log
echo " " >> /root/logs/start-bdp.log
echo -e "======啟動(dòng)hdfs完全分布式集群========" >> /root/logs/start-bdp.log
start-all.sh >> /root/logs/start-bdp.log
echo "$(date)-->啟動(dòng)hdfs完全分布式集群完成" >> /root/logs/start-bdp.log
echo " " >> /root/logs/start-bdp.log
echo " " >> /root/logs/start-bdp.log
echo " " >> /root/logs/start-bdp.log
echo " " >> /root/logs/start-bdp.log
echo "======當(dāng)前各個(gè)節(jié)點(diǎn)狀態(tài)為========" >> /root/logs/start-bdp.log
echo "$(date)======node001的zookeeper狀態(tài)為========" >> /root/logs/start-bdp.log
zkServer.sh status >> /root/logs/start-bdp.log
echo "$(date)======node002的zookeeper的狀態(tài)為========" >> /root/logs/start-bdp.log
ssh root@node002 "/opt/zookeeper-3.4.5/bin/zkServer.sh status" >> /root/logs/start-bdp.log
echo "$(date)======node003的zookeeper狀態(tài)為========" >> /root/logs/start-bdp.log
ssh root@node003 "/opt/zookeeper-3.4.5/bin/zkServer.sh status" >> /root/logs/start-bdp.log
echo "$(date)======node001的HDFS狀態(tài)========" >> /root/logs/start-bdp.log
jps >> /root/logs/start-bdp.log
echo "$(date)======node002的HDFS的狀態(tài)為========" >> /root/logs/start-bdp.log
ssh root@node002 "jps" >> /root/logs/start-bdp.log
echo "$(date)======node003的HDFS狀態(tài)為========" >> /root/logs/start-bdp.log
ssh root@node003 "jps" >> /root/logs/start-bdp.log
移動(dòng)到根節(jié)點(diǎn)創(chuàng)建存放日志的目錄:mkdir logs
執(zhí)行腳本:sh start-bdp.sh
查看日志:cat logs/start-bdp.log
日志如下:
Thu Sep 15 11:49:48 CST 2022======啟動(dòng)node001的zookeeper========
Starting zookeeper ... STARTED
Thu Sep 15 11:49:49 CST 2022======啟動(dòng)node002的zookeeper========
Starting zookeeper ... STARTED
Thu Sep 15 11:49:50 CST 2022======啟動(dòng)node003的zookeeper========
Starting zookeeper ... STARTED
======啟動(dòng)hdfs完全分布式集群========
Starting namenodes on [node001]
Last login: Thu Sep 15 11:46:48 CST 2022 on pts/0
Starting datanodes
Last login: Thu Sep 15 11:49:53 CST 2022 on pts/0
Starting secondary namenodes [node002]
Last login: Thu Sep 15 11:49:56 CST 2022 on pts/0
Starting resourcemanager
Last login: Thu Sep 15 11:50:03 CST 2022 on pts/0
Starting nodemanagers
Last login: Thu Sep 15 11:50:10 CST 2022 on pts/0
Thu Sep 15 11:50:21 CST 2022-->啟動(dòng)hdfs完全分布式集群完成
======當(dāng)前各個(gè)節(jié)點(diǎn)狀態(tài)為========
Thu Sep 15 11:50:21 CST 2022======node001的zookeeper狀態(tài)為========
Mode: follower
Thu Sep 15 11:50:21 CST 2022======node002的zookeeper的狀態(tài)為========
Mode: leader
Thu Sep 15 11:50:22 CST 2022======node003的zookeeper狀態(tài)為========
Mode: follower
Thu Sep 15 11:50:22 CST 2022======node001的HDFS狀態(tài)========
16160 NameNode
15937 QuorumPeerMain
16854 NodeManager
17222 Jps
16711 ResourceManager
16317 DataNode
Thu Sep 15 11:50:23 CST 2022======node002的HDFS的狀態(tài)為========
8933 QuorumPeerMain
9222 NodeManager
9020 DataNode
9133 SecondaryNameNode
9375 Jps
Thu Sep 15 11:50:23 CST 2022======node003的HDFS狀態(tài)為========
8195 NodeManager
7993 QuorumPeerMain
8073 DataNode
8348 Jps
六、HDFS_NameNode(NN)
功能
- 接受客戶端的讀寫服務(wù)
- NameNode?存放文件與?Block?的映射關(guān)系
- NameNode?會(huì)記錄?Block?與?DataNode?的映射關(guān)系,但是不會(huì)持久化
- 保存文件的元數(shù)據(jù)信息
- 文件的歸屬
- 文件的權(quán)限
- 文件的大小時(shí)間
- Block?信息,但是?block?的位置信息不會(huì)持久化?,?需要每次開啟集群的時(shí)候?DN?上報(bào)
- 收集 Block 的信息
- 系統(tǒng)啟動(dòng)時(shí)
- NN 關(guān)機(jī)的時(shí)候是不會(huì)存儲(chǔ)任意的 Block 與 DN 的映射信息
- DN 啟動(dòng)的時(shí)候,會(huì)將自己節(jié)點(diǎn)上存儲(chǔ)的 Block 信息匯報(bào)給 NN
- NN 接受請(qǐng)求之后重新生成映射關(guān)系
- Block--DN3
- 如果某個(gè)數(shù)據(jù)塊的副本數(shù)小于設(shè)置數(shù),那么 NN 會(huì)將這個(gè)副本拷貝到其他節(jié)點(diǎn)
?
- 集群運(yùn)行中
- NN 與 DN 保持心跳機(jī)制 , 三秒鐘發(fā)送一次
- 如果客戶端需要讀取或者上傳數(shù)據(jù)的時(shí)候, NN 可以知道 DN 的健康情況
- 可以讓客戶端讀取存活的 DN 節(jié)點(diǎn)
- 系統(tǒng)啟動(dòng)時(shí)
- 如果 DN 超過三秒沒有心跳,就認(rèn)為 DN 出現(xiàn)異常
- 不會(huì)讓新的數(shù)據(jù)讀寫到 DataNode
- 客戶訪問的時(shí)候不提供異常結(jié)點(diǎn)的地址
- 如果 DN 超過 10 分鐘 +30 秒沒有心跳,那么 NN 會(huì)將當(dāng)前 DN 存儲(chǔ)的數(shù)據(jù)轉(zhuǎn)存到其他節(jié)點(diǎn)
- 超時(shí)時(shí)長的計(jì)算公式為: timeout = 2 * heartbeat.recheck.interval + 10 *
- dfs.heartbeat.interval 。 而默認(rèn)的 heartbeat.recheck.interval 大小為 5分鐘, dfs.heartbeat.interval 默認(rèn)為 3 秒。
性能
- NameNode 為了效率,將所有的操作都在內(nèi)存中完成
- NameNode 不會(huì)和磁盤進(jìn)行任何的數(shù)據(jù)交換
- 問題 :
- 數(shù)據(jù)的持久化
- 數(shù)據(jù)保存在內(nèi)存中,掉電易失
- 小文件太多,作用內(nèi)存大
七、HDFS_DataNode(DN)
功能
- 存放的是文件的數(shù)據(jù)信息和驗(yàn)證文件完整性的校驗(yàn)信息
- 數(shù)據(jù)會(huì)存放在硬盤上
- 1m=1 條元數(shù)據(jù) 1G=1 條元數(shù)據(jù)
- NameNode 非常排斥存儲(chǔ)小文件,一般小文件在存儲(chǔ)之前需要進(jìn)行壓縮
- 匯報(bào)
- 啟動(dòng)時(shí)
- 匯報(bào)之前先驗(yàn)證 Block 文件是否被損壞
- 向 NN 匯報(bào)當(dāng)前 DN 上 block 的信息
- 運(yùn)行中
- 向 NN 保持心跳機(jī)制
- 客戶可以向 DN 讀寫數(shù)據(jù),
- 啟動(dòng)時(shí)
- 當(dāng)客戶端讀寫數(shù)據(jù)的時(shí)候,首先去 NN 查詢 file 與 block 與 dn 的映射
- 然后客戶端直接與 dn 建立連接,然后讀寫數(shù)據(jù)
?
- 然后客戶端直接與 dn 建立連接,然后讀寫數(shù)據(jù)
八、HDFS_SNN與測試
SecondaryNameNode
傳統(tǒng)解決方案
- 日志機(jī)制
- 做任何操作之前先記錄日志
- 當(dāng) NN 下次啟動(dòng)的時(shí)候,只需要重新按照以前的日志 “ 重做 ” 一遍即可
- 缺點(diǎn)
- edits 文件大小不可控,隨著時(shí)間的發(fā)展,集群啟動(dòng)的時(shí)間會(huì)越來越長
- 有可能日志中存在大量的無效日志
- 優(yōu)點(diǎn)
- 絕對(duì)不會(huì)丟失數(shù)據(jù)
- 拍攝快照
- 我們可以將內(nèi)存中的數(shù)據(jù)寫出到硬盤上
- 序列化
- 啟動(dòng)時(shí)還可以將硬盤上的數(shù)據(jù)寫回到內(nèi)存中
- 反序列化
- 缺點(diǎn)
- 關(guān)機(jī)時(shí)間過長
- 如果是異常關(guān)機(jī),數(shù)據(jù)還在內(nèi)存中,沒法寫入到硬盤
- 如果寫出頻率過高,導(dǎo)致內(nèi)存使用效率低( stop the world ) JVM
- 優(yōu)點(diǎn)
- 啟動(dòng)時(shí)間較短
SNN解決方案
解決思路(日志edit+快照fsimage)
- 讓日志大小可控
- 快照定時(shí)保存
- NameNode文件目錄
- 查看目錄:cd /var/bdp/hadoop/full/dfs/name/current/
- 顯示文件:ls?
- edits_0000000000000000001-000000000000000005
- edits_inprogress_0000000000000000020
- 當(dāng)前正在執(zhí)行操作的日志信息
- 這些日志信息還沒有被合并到鏡像中
- fsimage_0000000000000000002
- fsimage_0000000000000000002.md5
- fsimage_0000000000000000005
- fsimage_0000000000000000005.md5
- 完整性校驗(yàn)規(guī)則
- seen_txid -->5
- ?VERSION
解決方案
- 當(dāng)我們啟動(dòng)一個(gè)集群的時(shí)候,會(huì)產(chǎn)生四個(gè)文件
- edits_0000000000000000001
- fsimage_ edits_000000000000000000
- seen_txid
- VERSION
- 我們每次操作都會(huì)記錄日志-->edits-inprogress- edits_00000001
- 隨著時(shí)間的推移,日志文件會(huì)越來越大-當(dāng)達(dá)到閾值的時(shí)候(64M或3600秒)
-
dfs.namenode.checkpoint.period #每隔多久做一次checkpoint,默認(rèn)3600s dfs.namenode.checkpoint.txns #每隔多少次操作做一次checkpoint,默認(rèn)100萬次 dfs.namenode.checkpoint.check.period #每隔多久檢查一次操作次數(shù),默認(rèn)60s
- 會(huì)生成新的日志文件
- edits_inprogress-000000001 -->edits_0000001
- 創(chuàng)建新的日志文件 edits_inprogress-0000000016
SecondaryNameNode測試
SNN數(shù)據(jù)恢復(fù)
1.強(qiáng)行殺死NameNode節(jié)點(diǎn)
kill -9 進(jìn)程號(hào)
2.清空namenode下name中的fsimage和edits文件
rm -rf /var/bdp/hadoop/full/dfs/name/current/*
3.secondarynamenode下的name中的fsimage和edits復(fù)制到namenode對(duì)應(yīng)文件夾中
scp -r root@node002:/var/bdp/hadoop/full/dfs/namesecondary/current/* /var/bdp/hadoop/full/dfs/name/current
4.啟動(dòng)namenode
hadoop-daemon.sh start namenode
5.訪問namenode節(jié)點(diǎn)頁面
九、HDFS_安全模式和權(quán)限
安全模式
- 集群啟動(dòng)時(shí)的一個(gè)狀態(tài)
- 安全模式是 HDFS 的一種工作狀態(tài),處于安全模式的狀態(tài)下,只向客戶端提供文件的只讀視圖,不接受對(duì)命名空間的修改;同時(shí) NameNode 節(jié)點(diǎn)也不會(huì)進(jìn)行數(shù)據(jù)塊的復(fù)制或者刪除
- NameNode 啟動(dòng)時(shí)
- 首先將鏡像文件( fsimage )載入內(nèi)存,并執(zhí)行編輯日志( edits )中的各項(xiàng)操作
- 一旦在內(nèi)存中成功建立文件系統(tǒng)元數(shù)據(jù)的映像,則創(chuàng)建一個(gè)新的 fsimage 文件和一個(gè)空的編輯日志
- NameNode?開始監(jiān)聽?RPC?和?Http?請(qǐng)求。
- 此時(shí)?NameNode?處于安全模式,只接受客戶端的讀請(qǐng)求。
- 系統(tǒng)中的數(shù)據(jù)塊的位置并不是由?NameNode?維護(hù)的,而是以塊列表的形式存儲(chǔ)在?DataNode?中。
- 安全模式下
- 安全模式下,各個(gè) DataNode 會(huì)向 NameNode 發(fā)送自身的數(shù)據(jù)塊列表
- 當(dāng) NameNode 有足夠的數(shù)據(jù)塊信息后,便在 30 秒后退出安全模式
- NameNode 發(fā)現(xiàn)數(shù)據(jù)節(jié)點(diǎn)過少會(huì)啟動(dòng)數(shù)據(jù)塊復(fù)制過程
- 如果 NN 收集的 Block 信息沒有達(dá)到最少副本數(shù),就會(huì)將缺失的副本 , 從有的 DN 上拷貝到其他 DN
- dfs.replication.min=2
- 但是默認(rèn)最低副本數(shù)為 1
- 在拷貝的過程中系統(tǒng)還是處于安全模式
- 安全模式相關(guān)命令
- hadoop dfsadmin -safemode leave 強(qiáng)制 NameNode 退出安全模式
- hadoop dfsadmin -safemode enter 進(jìn)入安全模式
- hadoop dfsadmin -safemode get 查看安全模式狀態(tài)
- hadoop dfsadmin -safemode wait 等待一直到安全模式結(jié)束
權(quán)限
在hadoop-env.sh中配置
- HDFS?對(duì)權(quán)限的控制
- 只能防止好人做錯(cuò)事
- 不能防止壞人做壞事
- 你告訴他你是誰,他就認(rèn)為你是誰!
十、HDFS_機(jī)架感知與副本存放策略
節(jié)點(diǎn)距離
distance(/D1/R1/H1,/D1/R1/H1)=0 相同的 datanode
distance(/D1/R1/H1,/D1/R1/H3)=2 同一 rack 下的不同 datanode
distance(/D1/R1/H1,/D1/R2/H4)=4 同一 IDC 下的不同 datanode
distance(/D1/R1/H1,/D2/R3/H7)=6 不同 IDC 下的 datanode
機(jī)架感知
- 機(jī)架感知是為了保證副本在集群中的安全性
- 我們需要將節(jié)點(diǎn)放在不同的DN節(jié)點(diǎn)上,節(jié)點(diǎn)也需要一定的考量
- 可靠性,可用性,帶寬消耗
- 第一個(gè)節(jié)點(diǎn):
- 集群內(nèi)部(優(yōu)先考慮和客戶端相同的節(jié)點(diǎn)作為第一個(gè)節(jié)點(diǎn))
- 集群外部(選擇資源豐富且不繁忙的節(jié)點(diǎn)作為第一個(gè)節(jié)點(diǎn))
- 第二個(gè)節(jié)點(diǎn):
- 第二個(gè)節(jié)點(diǎn)選擇與第一個(gè)節(jié)點(diǎn)不同機(jī)架的其他節(jié)點(diǎn)
- 第三個(gè)節(jié)點(diǎn):
- 與第二個(gè)相同機(jī)架相同的其他節(jié)點(diǎn)
- 第N個(gè)節(jié)點(diǎn):
- 與前面節(jié)點(diǎn)不重復(fù)的其他節(jié)點(diǎn)
十一、HDFS_數(shù)據(jù)寫流程
寫數(shù)據(jù)就是將客戶端上的數(shù)據(jù)上傳到HDFS
宏觀過程
?1.客戶端向HDFS發(fā)送寫數(shù)據(jù)請(qǐng)求
創(chuàng)建目錄:hdfs dfs -mkdir -p /user/dfstest
上傳文件(隨便上傳一個(gè)大文件方便測試):hdfs dfs -put test.rar /user/dfstest? ??
2. ?filesystem通過rpc調(diào)用namenode的create方法
- nn首先檢查是否有足夠的空間權(quán)限等條件創(chuàng)建這個(gè)文件,或者這個(gè)路徑是否已經(jīng)存在,權(quán)限
- 有:NN會(huì)針對(duì)這個(gè)文件創(chuàng)建一個(gè)空的Entry對(duì)象,并返回成功狀態(tài)給DFS ?
- 沒有:直接拋出對(duì)應(yīng)的異常,給予客戶端錯(cuò)誤提示信息
3.如果DFS接收到成功的狀態(tài),會(huì)創(chuàng)建一個(gè)FSDataOutputStream的對(duì)象給客戶端使用
4.客戶端要向nn詢問第一個(gè)Block存放的位置
? ? ? ? NN通過機(jī)架感知策略 (node1 node 2 node8)
5.需要將客戶端和DN節(jié)點(diǎn)創(chuàng)建連接
? ? ? ? pipeline(管道)
? ? ? ? 客戶端和node1 創(chuàng)建連接 socket
? ? ? ? node1和 node2 創(chuàng)建連接 socket
? ? ? ? node2 和 Node8 創(chuàng)建連接 socket
6.客戶端按照文件塊切分?jǐn)?shù)據(jù),但是按照packet發(fā)送數(shù)據(jù)
? ? ? ? 默認(rèn)一個(gè)packet大小為64K,Block128M為2048個(gè)packet
7.客戶端通過pipeline管道開始使用FDSOutputStream對(duì)象將數(shù)據(jù)輸出
? ? ? ? 1. 客戶端首先將一個(gè) packet 發(fā)送給 node1, 同時(shí)給予 node1 一個(gè) ack 狀態(tài)
? ? ? ? 2. node1接受數(shù)據(jù)后會(huì)將數(shù)據(jù)繼續(xù)傳遞給 node2, 同時(shí)給予 node2 一個(gè) ack 狀態(tài)
? ? ? ? 3. node2接受數(shù)據(jù)后會(huì)將數(shù)據(jù)繼續(xù)傳遞給 node8, 同時(shí)給予 node8 一個(gè) ack 狀態(tài)
? ? ? ? 4. node8將這個(gè) packet 接受完成后,會(huì)響應(yīng)這個(gè) ack 給 node2 為 true
? ? ? ? 5. node2會(huì)響應(yīng)給 node1 , 同理 node1 響應(yīng)給客戶端
8. 客戶端接收到成功的狀態(tài) , 就認(rèn)為某個(gè) packet 發(fā)送成功了,直到當(dāng)前塊所有的 packet 都發(fā)送完成
9. 如果客戶端接收到最后一個(gè) pakcet 的成功狀態(tài) , 說明當(dāng)前 block 傳輸完成,管道就會(huì)被撤銷
10. 客戶端會(huì)將這個(gè)消息傳遞給 NN , NN 確認(rèn)傳輸完成
? ? ? ? 1. NN會(huì)將 block 的信息記錄到 Entry, 客戶端會(huì)繼續(xù)向 NN 詢問第二個(gè)塊的存儲(chǔ)位置 , 依次類推
? ? ? ? 2. block1 (node1 node2 node8)
? ? ? ? 3. block2 (node1 node8 node9)
? ? ? ? 4. ....
? ? ? ? 5. blockn(node1 node7 node9)
11. 當(dāng)所有的 block 傳輸完成后, NN 在 Entry 中存儲(chǔ)所有的 File 與 Block 與 DN 的映射關(guān)系關(guān)閉
? ? ? ? FsDataOutPutStream
微觀過程
1.客戶端首先從自己的硬盤中以流的形式將自己的數(shù)據(jù)讀取到緩存中
2.然后將緩存(buffer)中的數(shù)據(jù)以chunk(512B)和checksum(4B)的方式放入到packet(64k)
- chunk:checksum=128:1
- checksum:在數(shù)據(jù)處理和數(shù)據(jù)通信領(lǐng)域中,用于校驗(yàn)?zāi)康牡囊唤M數(shù)據(jù)項(xiàng)的和
- Packet中的數(shù)據(jù)分為兩類,一類是實(shí)際數(shù)據(jù)包,另一類是 header 包。
- 一個(gè) Packet 數(shù)據(jù)包的組成結(jié)構(gòu)
3.當(dāng)packet滿的時(shí)候添加到dataqueue
4.datastreamer開始從dataqueue隊(duì)列上讀取一個(gè)packet,通過FDSDataOPS發(fā)送到Poepleline
? ? ? ? ?在取出的時(shí)候,也會(huì)將 packet 加入到 ackQueue, 典型的生產(chǎn)者消費(fèi)者模式
5. 客戶端發(fā)送一個(gè) Packet 數(shù)據(jù)包以后開始接收 ack ,會(huì)有一個(gè)用來接收 ack 的 ResponseProcessor 進(jìn)程,如果收到成功的 ack
如果某一個(gè) packet 的 ack 為 true, 那么就從 ackqueue 刪除掉這個(gè) packet
如果某一個(gè) packet 的 ack 為 false, 將 ackqueue 中所有的 packet 重新掛載到 發(fā)送隊(duì)列 , 重新發(fā)送
十二、HDFS_數(shù)據(jù)讀流程
- 首先客戶端發(fā)送請(qǐng)求到 DFS ,申請(qǐng)讀取某一個(gè)文件
- hdfs dfs -get /user/dfstest/test.rar /opt
- DFS 去 NN 查找這個(gè)文件的信息 ( 權(quán)限 , 文件是否存在 )
- 如果文件不存在,拋出指定的錯(cuò)誤
- 如果文件存在,返回成功狀態(tài)
- DFS 創(chuàng)建 FSDataInputStream 對(duì)象,客戶端通過這個(gè)對(duì)象讀取數(shù)據(jù)
- 客戶端獲取文件第一個(gè) Block 信息 , 返回 DN1 DN2 DN8
- 客戶端直接就近原則選擇 DN1 對(duì)應(yīng)的數(shù)據(jù)即可
- 依次類推讀取其他塊的信息,直到最后一個(gè)塊 , 將 Block 合并成一個(gè)文件
- 關(guān)閉 FSDataInputStream
十三、Hadoop1?的困境
- 單點(diǎn)故障
- 每個(gè)群集只有一個(gè) NameNode , NameNode 存在單點(diǎn)故障( SPOF )。
- 如果該計(jì)算機(jī)或進(jìn)程不可用,則整個(gè)群集在整個(gè) NameNode 重新啟動(dòng)或在另一臺(tái)計(jì)算機(jī)上啟動(dòng)之前將不可用
- 如果發(fā)生意外事件(例如機(jī)器崩潰),則在操作員重新啟動(dòng) NameNode 之前,群集將不可用。
- 計(jì)劃內(nèi)的維護(hù)事件,例如 NameNode 計(jì)算機(jī)上的軟件或硬件升級(jí),將導(dǎo)致群集停機(jī)時(shí)間的延長。
- 水平擴(kuò)展
- 將來服務(wù)器啟動(dòng)的時(shí)候,啟動(dòng)速度慢
- namenode 隨著業(yè)務(wù)的增多,內(nèi)存占用也會(huì)越來越多
- 如果 namenode 內(nèi)存占滿,將無法繼續(xù)提供服務(wù)
- 業(yè)務(wù)隔離性差
- 存儲(chǔ):有可能我們需要存儲(chǔ)不同部門的數(shù)據(jù)
- 計(jì)算:有可能存在不同業(yè)務(wù)的計(jì)算流程
- 存儲(chǔ):有可能我們需要存儲(chǔ)不同部門的數(shù)據(jù)
- 項(xiàng)目后期 namenode 的吞吐量將會(huì)是集群的瓶頸
- 客戶端所有的請(qǐng)求都會(huì)先訪問 NameNode
- Hadoop2.x
- NameNode 節(jié)點(diǎn)的高可用
- HA--high availability
- NameNode 業(yè)余的水平擴(kuò)展
- Federation
- NameNode 節(jié)點(diǎn)的高可用
十四、HDFS_高可用Hadoop-HA
設(shè)計(jì)思想
- hadoop2.x 啟用了主備節(jié)點(diǎn)切換模式(1主 1 備)
- 當(dāng)主節(jié)點(diǎn)出現(xiàn)異常的時(shí)候,集群直接將備用(standby)節(jié)點(diǎn)切換成主節(jié)點(diǎn)
- 要求備用節(jié)點(diǎn)馬上就要工作
- 主備節(jié)點(diǎn)內(nèi)存幾乎同步
- 有獨(dú)立的線程對(duì)主備節(jié)點(diǎn)進(jìn)行監(jiān)控健康狀態(tài)
- 需要有一定的選舉機(jī)制,幫助我們確定主從關(guān)系
- 我們需要實(shí)時(shí)存儲(chǔ)日志的中間件
ANN
- Active NameNode 的功能和原理與?NN 的功能是一樣的
- 接受客戶端請(qǐng)求,查詢數(shù)據(jù)塊 DN 信息
- 存儲(chǔ)數(shù)據(jù)的元數(shù)據(jù)信息
- 數(shù)據(jù)文件: Block : DN 的映射關(guān)系?
- 工作
- 啟動(dòng)時(shí):接受 DN 的 block 匯報(bào)
- 運(yùn)行時(shí):和 DN 保持心跳 (3s,10m30s)
- 存儲(chǔ)介質(zhì)
- 完全基于內(nèi)存
- 優(yōu)點(diǎn):數(shù)據(jù)處理效率高
- 缺點(diǎn):數(shù)據(jù)的持久化 ( 日志 edits+ 快照 fsimage)
SNN
- Standby NameNode : NN 的備用節(jié)點(diǎn)
- 他和主節(jié)點(diǎn)做同樣的工作,但是它不會(huì)發(fā)出任何指令
- 存儲(chǔ):數(shù)據(jù)的元數(shù)據(jù)信息
- 數(shù)據(jù)文件: Block : DN 的映射關(guān)系
- 它的內(nèi)存數(shù)據(jù)和主節(jié)點(diǎn)內(nèi)存數(shù)據(jù)幾乎是一致的
- 工作:
- 啟動(dòng)時(shí):
- 接受 DN 的 block 匯報(bào)
- 運(yùn)行時(shí):
- 和 DN 保持心跳 (3s,10m30s)
- 啟動(dòng)時(shí):
- 存儲(chǔ)介質(zhì)
- 完全基于內(nèi)存
- 優(yōu)點(diǎn):數(shù)據(jù)處理效率高
- 缺點(diǎn):數(shù)據(jù)的持久化
- 合并日志文件和鏡像
- 當(dāng)搭建好集群的時(shí)候,格式化主備節(jié)點(diǎn)的時(shí)候, ANN 和 SNN 都會(huì)會(huì)默認(rèn)創(chuàng)建
- fsimage_000000000000000
- 當(dāng)我們操作 HDFS 的時(shí)候 ANN 會(huì)產(chǎn)生日志信息
- edits_inprogress_0000000000001
- 主節(jié)點(diǎn)會(huì)將日志文件中新增的數(shù)據(jù)同步到 JournalNode 集群上
- 所以只需要 snn 有操作的日志信息,就可以合并 fsImage 與 edits 信息 , 理論上是一直在合并數(shù)據(jù)
- fsimage --> 初始化創(chuàng)建
- edits--> 從 JournalNode 集群上定時(shí)同步
- 只要同步到 edits 文件,就開始于 fsimage 合并
- 當(dāng)達(dá)到閾值的時(shí)候,直接拍攝快照即可
- SNN 將合并好的 Fsimage 發(fā)送給 ANN,ANN 驗(yàn)證無誤后,存放到自己的目錄中
- 當(dāng)搭建好集群的時(shí)候,格式化主備節(jié)點(diǎn)的時(shí)候, ANN 和 SNN 都會(huì)會(huì)默認(rèn)創(chuàng)建
DataNode(DN)
- 存儲(chǔ)
- 文件的 Block 數(shù)據(jù)
- 介質(zhì)
- 硬盤
- 啟動(dòng)時(shí):
- 同時(shí)向兩個(gè) NN 匯報(bào) Block 信息
- 運(yùn)行中
- 同時(shí)和兩個(gè) NN 節(jié)點(diǎn)保持心跳機(jī)制
?
- 同時(shí)和兩個(gè) NN 節(jié)點(diǎn)保持心跳機(jī)制
QJM
- Quorum JournalNode Manager 共享存儲(chǔ)系統(tǒng), NameNode 通過共享存儲(chǔ)系統(tǒng)實(shí)現(xiàn)日志數(shù)據(jù)同步。
- JournalNode 是一個(gè)獨(dú)立的小集群,它的實(shí)現(xiàn)原理和 Zookeeper 的一致 ( Paxos)
- ANN 產(chǎn)生日志文件的時(shí)候,就會(huì)同時(shí)發(fā)送到 JournalNode 的集群中每個(gè)節(jié)點(diǎn)上
- JournalNode 不要求所有的 jn 節(jié)點(diǎn)都接收到日志,只要有半數(shù)以上的( n/2+1 )節(jié)點(diǎn)接受收到日志,那么本條日志就生效
- SNN 每間隔一段時(shí)間就去 QJM 上面取回最新的日志
- SNN 上的日志有可能不是最新的
- HA 集群的狀態(tài)正確至關(guān)重要,一次只能有一個(gè) NameNode 處于活動(dòng)狀態(tài)。
- JournalNode 只允許單個(gè) NameNode 成為作者。在故障轉(zhuǎn)移期間,將變?yōu)榛顒?dòng)狀態(tài)的 NameNode將承擔(dān)寫入 JournalNodes 的角色,這將有效地防止另一個(gè) NameNode 繼續(xù)處于活動(dòng)狀態(tài),從而使新的 Active 節(jié)點(diǎn)可以安全地進(jìn)行故障轉(zhuǎn)移。
ZKFC
- Failover Controller( 故障轉(zhuǎn)移控制器 )
- 對(duì) NameNode 的主備切換進(jìn)行總體控制,能及時(shí)檢測到 NameNode 的健康狀況
- 在主 NameNode 故障時(shí)借助 Zookeeper 實(shí)現(xiàn)自動(dòng)的主備選舉和切換
- 為了防止因?yàn)?NN 的 GC 失敗導(dǎo)致心跳受影響, ZKFC 作為一個(gè) deamon 進(jìn)程從 NN 分離出來
- 啟動(dòng)時(shí):
- 當(dāng)集群啟動(dòng)時(shí),主備節(jié)點(diǎn)的概念是很模糊的
- 當(dāng) ZKFC 只檢查到一個(gè)節(jié)點(diǎn)是健康狀態(tài),直接將其設(shè)置為主節(jié)點(diǎn)
- 當(dāng) zkfc 檢查到兩個(gè) NN 節(jié)點(diǎn)是的健康狀態(tài),發(fā)起投票機(jī)制
- 選出一個(gè)主節(jié)點(diǎn),一個(gè)備用節(jié)點(diǎn),并修改主備節(jié)點(diǎn)的狀態(tài)
- 運(yùn)行時(shí):
- 由 ZKFailoverController 、 HealthMonitor 和 ActiveStandbyElector 這 3 個(gè)組件來協(xié)同實(shí)現(xiàn)主備切換
- ZKFailoverController 啟動(dòng)的時(shí)候會(huì)創(chuàng)建 HealthMonitor 和 ActiveStandbyElector 這兩個(gè)主要的內(nèi)部組件
- HealthMonitor 主要負(fù)責(zé)檢測 NameNode 的健康狀態(tài)
- ActiveStandbyElector 主要負(fù)責(zé)完成自動(dòng)的主備選舉,內(nèi)部封裝了 Zookeeper 的處理邏輯
- 由 ZKFailoverController 、 HealthMonitor 和 ActiveStandbyElector 這 3 個(gè)組件來協(xié)同實(shí)現(xiàn)主備切換
- 主備節(jié)點(diǎn)正常切換
- NameNode 在選舉成功后, ActiveStandbyElector 會(huì)在 zk 上創(chuàng)建一個(gè)ActiveStandbyElectorLock 臨時(shí)節(jié)點(diǎn),而沒有選舉成功的備 NameNode 中的ActiveStandbyElector 會(huì)監(jiān)控這個(gè)節(jié)點(diǎn)
- 如果 Active NameNode 對(duì)應(yīng)的 HealthMonitor 檢測到 NameNode 的狀態(tài)異常時(shí),ZKFailoverController 會(huì)主動(dòng)刪除當(dāng)前在 Zookeeper 上建立的臨時(shí)節(jié)點(diǎn)ActiveStandbyElectorLock
- 如果是 Active NameNode 的機(jī)器整個(gè)宕掉的話,那么跟 zookeeper 連接的客戶端線程也掛了 , 會(huì)話結(jié)束 , 那么根據(jù) Zookeepe 的臨時(shí)節(jié)點(diǎn)特性, ActiveStandbyElectorLock 節(jié)點(diǎn)會(huì)自動(dòng)被刪除,從而也會(huì)自動(dòng)進(jìn)行一次主備切換
- 處于 Standby 狀態(tài)的 NameNode 的 ActiveStandbyElector 注冊(cè)的監(jiān)聽器就會(huì)收到這個(gè)節(jié)點(diǎn)的 NodeDeleted 事件,并創(chuàng)建 ActiveStandbyElectorLock 臨時(shí)節(jié)點(diǎn),本來處于 Standby 狀態(tài)的 NameNode 就選舉為 Active NameNode 并隨后開始切換為 Active 狀態(tài)。
Zookeeper
- 為主備切換控制器提供主備選舉支持。
- 輔助投票
- 和 ZKFC 保持心跳機(jī)制,確定 ZKFC 的存活
十五、HDFS_高可用腦裂
腦裂?brain-split
- 定義
- 腦裂是 Hadoop2.X 版本后出現(xiàn)的全新問題,實(shí)際運(yùn)行過程中很有可能出現(xiàn)兩個(gè) namenode 同時(shí)服務(wù)于整個(gè)集群的情況,這種情況稱之為腦裂。
- 原因
- 腦裂通常發(fā)生在主從 namenode 切換時(shí),由于 ActiveNameNode 的網(wǎng)絡(luò)延遲、設(shè)備故障等問題,另一個(gè) NameNode 會(huì)認(rèn)為活躍的 NameNode 成為失效狀態(tài),此時(shí)StandbyNameNode 會(huì)轉(zhuǎn)換成活躍狀態(tài),此時(shí)集群中將會(huì)出現(xiàn)兩個(gè)活躍的 namenode 。因此,可能出現(xiàn)的因素有網(wǎng)絡(luò)延遲、心跳故障、設(shè)備故障等。
- 腦裂場景
- NameNode 可能會(huì)出現(xiàn)這種情況, NameNode 在垃圾回收( GC )時(shí),可能會(huì)在長時(shí)間內(nèi)整個(gè)系統(tǒng)無響應(yīng)
- zkfc 客戶端也就無法向 zk 寫入心跳信息,這樣的話可能會(huì)導(dǎo)致臨時(shí)節(jié)點(diǎn)掉線,備 NameNode會(huì)切換到 Active 狀態(tài)
- 這種情況可能會(huì)導(dǎo)致整個(gè)集群會(huì)有同時(shí)有兩個(gè) Active NameNode
- 腦裂問題的解決方案是隔離( Fencing )
- 1. 第三方共享存儲(chǔ):任一時(shí)刻,只有一個(gè) NN 可以寫入;
- 2.DataNode :需要保證只有一個(gè) NN 發(fā)出與管理數(shù)據(jù)副本有關(guān)的命令;
- 3.Client 需要保證同一時(shí)刻只有一個(gè) NN 能夠?qū)?Client 的請(qǐng)求發(fā)出正確的響應(yīng)。
- (a) 每個(gè) NN 改變狀態(tài)的時(shí)候,向 DN 發(fā)送自己的狀態(tài)和一個(gè)本次選舉對(duì)應(yīng)的序列號(hào)。
- (b) DN 在運(yùn)行過程中維護(hù)此序列號(hào),當(dāng) failover 時(shí),新的 NN 在返回 DN 心跳時(shí)會(huì)返回自己的 active 狀態(tài)和一個(gè)更大的序列號(hào)。DN 接收到這個(gè)返回是認(rèn)為該 NN 為新的 active 。
- (c) 如果這時(shí)原來的 active (比如 GC )恢復(fù),返回給 DN 的心跳信息包含 active 狀態(tài)和原來的序列號(hào),這時(shí) DN 就會(huì)拒絕這個(gè) NN 的命令。
- 解決方案
- ActiveStandbyElector 為了實(shí)現(xiàn) fencing ,當(dāng) NN 成為 ANN 之后創(chuàng)建 Zookeeper 臨時(shí)節(jié)點(diǎn)ActiveStandbyElectorLock ,創(chuàng)建 ActiveBreadCrumb 的持久節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)里面保存了這個(gè)Active NameNode 的地址信息 (node-01)
- Active NameNode 的 ActiveStandbyElector 在正常的狀態(tài)下關(guān)閉 Zookeeper Session 的時(shí)候,會(huì)一起刪除這個(gè)持久節(jié)點(diǎn)
- 但如果 ActiveStandbyElector 在異常的狀態(tài)下關(guān)閉,那么由于 /hadoopha/${dfs.nameservices}/ActiveBreadCrumb 是持久節(jié)點(diǎn),會(huì)一直保留下來,后面當(dāng)另一個(gè)NameNode 選主成功之后,會(huì)注意到上一個(gè) Active NameNode 遺留下來的這個(gè)節(jié)點(diǎn),從而會(huì)回調(diào) ZKFailoverController 的方法對(duì)舊的 Active NameNode 進(jìn)行 fencing 。
- 首先嘗試調(diào)用這個(gè)舊 Active NameNode 的 HAServiceProtocol RPC 接口的transitionToStandby 方法,看能不能把它轉(zhuǎn)換為 Standby 狀態(tài);
- 如果 transitionToStandby 方法調(diào)用失敗,那么就執(zhí)行 Hadoop 配置文件之中預(yù)定義的隔離措施。
- 1. sshfence :通過 SSH 登錄到目標(biāo)機(jī)器上,執(zhí)行命令 fuser 將對(duì)應(yīng)的進(jìn)程殺死
- 2. shellfence :執(zhí)行一個(gè)用戶自定義的 shell 腳本來將對(duì)應(yīng)的進(jìn)程隔離
- 在成功地執(zhí)行完成 fencing 之后,選主成功的 ActiveStandbyElector 才會(huì)回調(diào)ZKFailoverController 的 becomeActive 方法將對(duì)應(yīng)的 NameNode 轉(zhuǎn)換為 Active 狀態(tài),開始對(duì)外提供服務(wù)。
- 新的主創(chuàng)建臨時(shí)節(jié)點(diǎn) ActiveStandbyElectorLock ,創(chuàng)建持久化節(jié)點(diǎn) ActiveBreadCrumb ,并將自己的主機(jī)地址 Node02 賦值給初始化節(jié)點(diǎn)
十六、HDFS_水平擴(kuò)展聯(lián)邦機(jī)制
為什么需要聯(lián)邦
單 NameNode 的架構(gòu)存在的問題:當(dāng)集群中數(shù)據(jù)增長到一定規(guī)模后,NameNode 進(jìn)程占用的內(nèi)存可能會(huì)達(dá)到成百上千 GB(調(diào)大 NameNode 的 JVM 堆內(nèi)存已無可能),此時(shí),NameNode 成了集群的性能瓶頸。
為了提高 HDFS 的水平擴(kuò)展能力,提出了Federation(聯(lián)邦,聯(lián)盟)機(jī)制。
Federation 是 NameNode 的 Federation,也就是會(huì)有多個(gè) NameNode,而多個(gè) NameNode 也就意味著有多個(gè) namespac(命名空間),不同于 HA 模式下 Active 和 Standby 有各自的命名空間,聯(lián)邦環(huán)境下的多 NameNode 共享同一個(gè) namespace。
來看一下命名空間在 HDFS 架構(gòu)中的位置:
現(xiàn)有的 HDFS 可以簡單分為?數(shù)據(jù)管理?和?數(shù)據(jù)存儲(chǔ)?2層:
所有關(guān)于存儲(chǔ)數(shù)據(jù)的信息和管理,都是由 NameNode 負(fù)責(zé);
而真實(shí)數(shù)據(jù)的存儲(chǔ)則是在各個(gè) DataNode 下完成。
這些被同一個(gè) NameNode 所管理的數(shù)據(jù)都在同一個(gè) namespace 下,一個(gè) namespace 對(duì)應(yīng)一個(gè)Block Pool(所有數(shù)據(jù)塊的集合)。
Federation 架構(gòu)設(shè)計(jì)
再強(qiáng)調(diào)一遍:HDFS Federation 是用來解決 NameNode 內(nèi)存瓶頸問題的橫向擴(kuò)展方案。
Federation 意味著在集群中將會(huì)有多個(gè) NameNode,這些 NameNode 相互獨(dú)立且不需要協(xié)調(diào),它們只需要管理自己所屬的數(shù)據(jù)塊即可。
分布式的 DataNode 作為公共的數(shù)據(jù)塊存儲(chǔ)設(shè)備,被所有的 NameNode 共用:每個(gè) DataNode 都要向集群中所有的 NameNode 注冊(cè),且周期性地向所有 NameNode 發(fā)送心跳和塊報(bào)告,并執(zhí)行所有 NameNode 下發(fā)的命令。
Federation 架構(gòu)中,DataNode上 會(huì)有多個(gè) Block Pool 下,在 DataNode 的 datadir 目錄下能看到以?BP-xx.xx.xx.xx
?開頭的目錄。
從上圖可以看出來:
多個(gè) NameNode 共用一個(gè)集群里的所有存儲(chǔ)資源,每個(gè) NameNode 都可以單獨(dú)對(duì)外提供服務(wù);
每個(gè) NameNode 都會(huì)定義一個(gè) Block Pool,有單獨(dú)的 id,每個(gè) DataNode 都為所有 Block Pool 提供存儲(chǔ)。
DataNode 會(huì)按照存儲(chǔ)池 id 向其對(duì)應(yīng)的 NameNode 匯報(bào)塊信息,同時(shí),DataNode 會(huì)向所有 NameNode 匯報(bào)本地存儲(chǔ)可用資源情況。
HDFS Federation 的不足
HDFS Federation 并沒有完全解決單點(diǎn)故障問題。
雖然集群中有多個(gè) NameNode(namespace),但是從單個(gè) NameNode(namespace)看,仍然存在單點(diǎn)故障:
如果某個(gè) NameNode 服務(wù)發(fā)生故障,其管理的文件便不能被訪問。
Federation 架構(gòu)中每個(gè)NameNode 同樣配有一個(gè) Secondary NameNode,用于協(xié)助 NameNode 管理元數(shù)據(jù)信息(FSImage 和 EditLog)。
所以超大規(guī)模的集群,一般都會(huì)采用 HA + Federation 的部署方案,也就是每個(gè)聯(lián)合的 NameNode 都是 HA 的,這樣就解決了 NameNode 的單點(diǎn)故障問題 和 橫向擴(kuò)容問題。
十七、HDFS_HA搭建
注:這里搭建HA與上文搭建完全分布式集群不是串行而是并行,故其所有配置文件應(yīng)重新編寫,不能套用完全分布式集群的配置文件。即:從頭再來
初始化
將hadoop-3.1.2.tar.gz安裝包重新解壓覆蓋原先文件即可。注意:操作之前記得拍攝快照。
tar -zxvf hadoop-3.1.2.tar.gz -C /opt/
角色分配
節(jié)點(diǎn)\角色 | ZK | NN | DN | JN | ZKFC |
node001 | √ | √ | √ | √ | |
node002 | √ | √ | √ | √ | √ |
node003 |
√ | √ | √ |
配置文件
hadoop-env.sh
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/hadoop-env.sh
?末行添加:
export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_ZKFC_USER=root
export HDFS_JOURNALNODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root
core-site.???????xml
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/core-s???????ite.xml
添加:
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://bdp</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/bdp/hadoop/ha</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>node001:2181,node002:2181,node003:2181</value>
</property>
<property>
<name>hadoop.http.staticuser.user</name>
<value>root</value>
</property>
</configuration>
hdfs-site.xml
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/hdfs-site.xml
添加:
<configuration>
<property>
<name>dfs.nameservices</name>
<value>bdp</value>
</property>
<!-- 指定cluster的兩個(gè)namenode的名稱分別為nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.bdp</name>
<value>nn1,nn2</value>
</property>
<!-- 配置nn1,nn2的rpc通信端口 -->
<property>
<name>dfs.namenode.rpc-address.bdp.nn1</name>
<value>node001:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.bdp.nn2</name>
<value>node002:8020</value>
</property>
<!-- 配置nn1,nn2的http通信端口 -->
<property>
<name>dfs.namenode.http-address.bdp.nn1</name>
<value>node001:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.bdp.nn2</name>
<value>node002:9870</value>
</property>
<!-- 指定namenode元數(shù)據(jù)存儲(chǔ)在journalnode中的路徑 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node001:8485;node002:8485;node003:8485/cluster</value>
</property>
<!-- 指定journalnode日志文件存儲(chǔ)的路徑 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/var/bdp/hadoop/qjm</value>
</property>
<!-- 指定HDFS客戶端連接active namenode的java類 -->
<property>
<name>dfs.client.failover.proxy.provider.bdp</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置隔離機(jī)制為ssh -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
<value>shell(true)</value>
</property>
<!-- 指定秘鑰的位置 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<!-- 指定秘鑰的位置 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<!-- 開啟自動(dòng)故障轉(zhuǎn)移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
</configuration>
workers
終端輸入:vim /opt/hadoop-3.1.2/etc/hadoop/workers
刪除:localhost
添加:
node001
node002
node003
分發(fā)
將修改好的配置文件發(fā)送到其他節(jié)點(diǎn)(時(shí)間較長)
傳到node002:scp -r /opt/hadoop-3.1.2/ node002:/opt/
傳到node003:scp -r /opt/hadoop-3.1.2/ node003:/opt/
啟動(dòng)
啟動(dòng)zookeeper,三臺(tái)都需要啟動(dòng)
三臺(tái)機(jī)器終端輸入:zkServer.sh start
啟動(dòng)JN(journalnode),三臺(tái)都需啟動(dòng)
hadoop-daemon.sh start journalnode
格式化,在一臺(tái)NN上執(zhí)行(這里選擇node001)
#格式化
hdfs namenode -format
#啟動(dòng)當(dāng)前NN
hadoop-daemon.sh start namenode
執(zhí)行同步,沒有格式化的NN上執(zhí)行,在另外一臺(tái)namenode上面執(zhí)行(這里選擇node002)
hdfs namenode -bootstrapStandby
格式化ZK(在node001上執(zhí)行)
hdfs zkfc -formatZK
啟動(dòng)hdfs集群(在node001上執(zhí)行)
start-dfs.sh
?到此HA集群搭建完成!
十八、HDFS_java訪問hdfs集群
HDFS的Java訪問接口
- 1)org.apache.hadoop.fs.FileSystem
- 是一個(gè)通用的文件系統(tǒng)API,提供了不同文件系統(tǒng)的統(tǒng)一訪問方式。
- 2)org.apache.hadoop.fs.Path
- 是Hadoop文件系統(tǒng)中統(tǒng)一的文件或目錄描述,類似于java.io.File對(duì)本地文件系統(tǒng)的文件或目錄描述。
- 3)org.apache.hadoop.conf.Configuration
- 讀取、解析配置文件(如core-site.xml/hdfs-default.xml/hdfs-site.xml等),或添加配置的工具類
- 4)org.apache.hadoop.fs.FSDataOutputStream
- 對(duì)Hadoop中數(shù)據(jù)輸出流的統(tǒng)一封裝
- 5)org.apache.hadoop.fs.FSDataInputStream
- 對(duì)Hadoop中數(shù)據(jù)輸入流的統(tǒng)一封裝
Java訪問HDFS主要編程步驟
- 1)構(gòu)建Configuration對(duì)象,讀取并解析相關(guān)配置文件
- Configuration conf=new Configuration();
- 2)設(shè)置相關(guān)屬性
- conf.set("fs.defaultFS","hdfs://IP:9000");
- 3)獲取特定文件系統(tǒng)實(shí)例fs(以HDFS文件系統(tǒng)實(shí)例)
- FileSystem fs=FileSystem.get(new URI("hdfs://IP:9000"),conf,“hdfs");
- 4)通過文件系統(tǒng)實(shí)例fs進(jìn)行文件操作(以刪除文件實(shí)例)
- fs.delete(new Path("/user/liuhl/someWords.txt"));
使用FileSystem API讀取數(shù)據(jù)文件
有兩個(gè)靜態(tài)工廠方法來獲取FileSystem實(shí)例文件系統(tǒng)。
常用的是第二個(gè)和第四個(gè)
編程實(shí)現(xiàn)
環(huán)境介紹
使用的是IDEA+Maven來進(jìn)行測試
Maven的pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.libing</groupId>
<artifactId>hdfa</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-auth</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
</project>
代碼實(shí)操
上傳文件到HA集群
package com.libing.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
/**
* @author liar
* @version 1.0
* @date 2022/9/17 21:26
*/
public class UploadTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//構(gòu)建Configuration對(duì)象,讀取并解析相關(guān)配置文件
Configuration conf = new Configuration();
/**
* 這些都是HA集群中配置文件的信息
*/
//設(shè)置相關(guān)屬性
conf.set("fs.defaultFS", "hdfs://bdp");
conf.set("dfs.nameservices", "bdp");
conf.set("dfs.ha.namenodes.bdp", "nn1,nn2");
conf.set("dfs.namenode.rpc-address.bdp.nn1", "192.168.1.101:8020");
conf.set("dfs.namenode.rpc-address.bdp.nn2", "192.168.1.102:8020");
conf.set("dfs.client.failover.proxy.provider.bdp",
"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
try {
//獲取特定文件系統(tǒng)實(shí)例fs
FileSystem fs = FileSystem.get(new URI("hdfs://bdp"), conf,"root");
//創(chuàng)建/user/hdfs/test文件目錄
boolean b=fs.mkdirs(new Path("/user/hdfs/test"));
if (b){
//將本地目錄中的文件上傳到集群中
//通過文件系統(tǒng)實(shí)例fs進(jìn)行文件操作
fs.copyFromLocalFile(new Path("D:\\test\\test.txt"), new Path("/user/hdfs/test/test-1.txt"));
}else {
System.out.println("創(chuàng)建文件夾失敗");
}
fs.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
下載集群中文件
package com.libing.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
/**
* @author liar
* @version 1.0
* @date 2022/9/17 21:36
*/
public class DownloadTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://bdp");
conf.set("dfs.nameservices", "bdp");
conf.set("dfs.ha.namenodes.bdp", "nn1,nn2");
conf.set("dfs.namenode.rpc-address.bdp.nn1", "192.168.1.101:8020");
conf.set("dfs.namenode.rpc-address.bdp.nn2", "192.168.1.102:8020");
conf.set("dfs.client.failover.proxy.provider.bdp",
"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
//這之上的代碼基本不變
try {
FileSystem fs = FileSystem.get(new URI("hdfs://bdp"), conf,"root");
//基本上 代碼的變化在這里,主要為對(duì)集群中文件的增刪改查
fs.copyToLocalFile(new Path("/user/hdfs/test/test-1.txt"),new Path("D:\\test\\test-local.txt"));
fs.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
這里淺談一下這個(gè).crc文件的由來:
CRC數(shù)據(jù)校驗(yàn)文件
- Hadoop系統(tǒng)為了保證數(shù)據(jù)的一致性,會(huì)對(duì)文件生成相應(yīng)的校驗(yàn)文件(.crc文件),并在讀寫的時(shí)候進(jìn)行校驗(yàn),確保數(shù)據(jù)的準(zhǔn)確性。
- hdfs為了保證數(shù)據(jù)的一致性,每次寫文件時(shí),針對(duì)數(shù)據(jù)的io.bytes.per.checksum字節(jié),都會(huì)創(chuàng)建一個(gè)單獨(dú)的校驗(yàn)和。默認(rèn)值為512字節(jié),因?yàn)閏rc-32校驗(yàn)是4字節(jié),存儲(chǔ)開銷小于1%。而客戶端讀取數(shù)據(jù)時(shí),默認(rèn)會(huì)驗(yàn)證數(shù)據(jù)的crc校驗(yàn)和。除此之外,每個(gè)數(shù)據(jù)節(jié)點(diǎn)還會(huì)在后臺(tái)線程運(yùn)行一個(gè)數(shù)據(jù)塊檢測程序,定期檢查存儲(chǔ)在數(shù)據(jù)節(jié)點(diǎn)上的所有塊。當(dāng)塊和對(duì)應(yīng)的crc校驗(yàn)匹配不上,由于hdfs存儲(chǔ)著塊的副本,它可以復(fù)制正確的副本替換出錯(cuò)的副本。
簡單來說他就是做校驗(yàn)工作的,相當(dāng)于小區(qū)保安,你不是業(yè)主就不讓你進(jìn)去是一個(gè)道理。
十九、HDFS_IDEA插件訪問hdfs集群
安裝插件
使用
在右側(cè)邊欄打開big data tools
點(diǎn)擊左上角+號(hào),選擇HDFS
結(jié)語
本文較長,如果你能堅(jiān)持看完,也能發(fā)現(xiàn)作者的用心。
如果文章有什么出錯(cuò)或者你對(duì)文章有何建議或意見都可以通過我的郵箱聯(lián)系到我:
719167291@qq.com
參考資料
hdfs?- 百度百科
Hadoop-HDFS文章來源:http://www.zghlxwxcb.cn/news/detail-417952.html
Hadoop集群完全分布式的搭建文章來源地址http://www.zghlxwxcb.cn/news/detail-417952.html
到了這里,關(guān)于Hadoop-HDFS詳解與HA,完全分布式集群搭建(細(xì)到令人發(fā)指的教程)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!