寫(xiě)在前面
我自己一直比較喜歡大數(shù)據(jù)這個(gè)方向的工作,雖然自己也在大數(shù)據(jù)相關(guān)的崗位上工作了小兩年坛怪,但一直沒(méi)有系統(tǒng)的學(xué)習(xí)過(guò)大數(shù)據(jù)相關(guān)的知識(shí)申眼。
說(shuō)到自身經(jīng)歷,可能和大部分程序員一樣潮饱,一直混跡于小公司来氧,我從第一家公司離職的理由就是拖欠工資,那個(gè)時(shí)候又是剛畢業(yè)饼齿,手里沒(méi)有一點(diǎn)積蓄饲漾,后來(lái)實(shí)在沒(méi)辦法只能離職求活路。不過(guò)很感謝第一家公司缕溉,在那是我進(jìn)步最快的地方考传,我從事大數(shù)據(jù)崗位也是那家公司花錢(qián)讓我去學(xué)習(xí)的。除了是小公司证鸥,其他的都很好僚楞,技術(shù)氛圍很棒!第二家公司雖然比較大枉层,但是屬于項(xiàng)目外包型公司(雖然我所在的部門(mén)屬于自研型泉褐,但還是外包的干法,我依舊記得我入職之后才發(fā)現(xiàn)公司代碼沒(méi)有版本管理鸟蜡,所有代碼都在主分支上膜赃,沒(méi)有一份技術(shù)文檔,全靠口口相傳)揉忘。
今年疫情原因跳座,各個(gè)行業(yè)裁員的裁員端铛,降薪的降薪,我在的公司也不例外疲眷,全員降薪30%禾蚕,然而周末也沒(méi)了,瘋狂趕項(xiàng)目進(jìn)度狂丝,我最多的時(shí)候同時(shí)支持了五個(gè)項(xiàng)目組的報(bào)表開(kāi)發(fā)换淆,每天做夢(mèng)都?jí)粢?jiàn)自己在催著改報(bào)表。
更恐怖的是開(kāi)發(fā)這個(gè)行業(yè)几颜,尤其是有外包性質(zhì)倍试,門(mén)檻極低,低到令人發(fā)指蛋哭,我在公司下面帶了三個(gè)那種培訓(xùn)機(jī)構(gòu)出來(lái)的易猫,都是學(xué)了幾個(gè)月轉(zhuǎn)身包裝簡(jiǎn)歷就出來(lái)面試了,那的工資低還比你能加班具壮!
后來(lái)實(shí)在不想每天這樣疲于拼命的機(jī)械式生活拾并,想著多花時(shí)間去學(xué)習(xí)梦抢,然后跳槽去好一點(diǎn)的公司险耀!然而現(xiàn)實(shí)告訴你旷痕,我最缺的就是時(shí)間拿霉!直到拉勾推出的大數(shù)據(jù)高薪訓(xùn)練營(yíng)蹬竖。關(guān)于技術(shù)類(lèi)的學(xué)習(xí)色瘩,我有點(diǎn)排斥找培訓(xùn)機(jī)構(gòu)锥腻,覺(jué)得自己可以通過(guò)自學(xué)吠勘,在網(wǎng)上翻閱資料啊性芬,找視頻之類(lèi)的方式學(xué),因?yàn)橄嘈抛约旱膶W(xué)習(xí)能力剧防。但是大家也都知道植锉,網(wǎng)上找的這些東西都能學(xué)會(huì),也可以看得懂峭拘。但是當(dāng)自己學(xué)多了就感覺(jué)自己學(xué)的很雜俊庇,一點(diǎn)都沒(méi)有系統(tǒng)性的學(xué)。而且相對(duì)于網(wǎng)上找的免費(fèi)的視頻鸡挠,內(nèi)容很沒(méi)有深度辉饱,TB上買(mǎi)的視頻有些章節(jié)的確實(shí)還行,但是感覺(jué)是那種很久之前的東西拿出來(lái)不停的賣(mài)拣展,而且關(guān)于技術(shù)方面的東西彭沼,肯定是會(huì)有不明白的地方,當(dāng)然遇到這些肯定第一時(shí)間是自己去網(wǎng)絡(luò)上找找解決方案备埃,或者去了解為什么姓惑。但是很多東西確實(shí)在網(wǎng)絡(luò)上找不到褐奴,久而久之,就積累了各種問(wèn)題挺益。
之前也看過(guò)很多培訓(xùn)機(jī)構(gòu)歉糜,像什么八斗學(xué)院,馬士兵教育望众,金訊教育等等匪补,經(jīng)常發(fā)一些二學(xué)員就業(yè)的截圖,薪資都特別高烂翰,但其實(shí)在這一行的都知道夯缺,大數(shù)據(jù)這塊薪資雖然高,但也沒(méi)有高特別多甘耿,只是門(mén)檻高踊兜,說(shuō)實(shí)話,很討厭這種虛假營(yíng)銷(xiāo)佳恬。
選擇拉勾的原因
1. 朋友推薦
剛開(kāi)始知道拉勾除了Java高薪訓(xùn)練營(yíng)捏境,但是并不是很感興趣,后來(lái)朋友報(bào)名了Java高薪訓(xùn)練營(yíng)毁葱,反饋很好垫言,恰逢拉勾推出了大數(shù)據(jù)高薪訓(xùn)練營(yíng),就想著說(shuō)同一家公司的課程倾剿,質(zhì)量應(yīng)該差不多筷频,就抱著試一試的想法找拉勾的老師聊了聊,聽(tīng)完介紹感覺(jué)還可以前痘,就報(bào)名了凛捏。
2. 拉勾本身
拉勾本身就是做招聘的,對(duì)企業(yè)需求這一塊更加了解企業(yè)需要什么樣能力的人芹缔,那么他們的課程在這塊針對(duì)性肯定比其他機(jī)構(gòu)好
結(jié)果
1. 個(gè)人收獲
算算從開(kāi)班到現(xiàn)在坯癣,已經(jīng)五個(gè)月了,課程已經(jīng)學(xué)了一半乖菱,不是我學(xué)的很慢坡锡,而是課程質(zhì)量真的很高,每一個(gè)模塊單獨(dú)拿出來(lái)都可以是一門(mén)課了窒所,特別是一塊內(nèi)容學(xué)完就有一個(gè)實(shí)際項(xiàng)目等著你去做鹉勒,而不是demo!現(xiàn)在養(yǎng)成了學(xué)習(xí)的習(xí)慣之后完全停不下來(lái)了吵取!在這里禽额,我已經(jīng)經(jīng)歷了完整的離線數(shù)倉(cāng)開(kāi)發(fā),包括服務(wù)器選型,技術(shù)選型等等脯倒,在需求這塊实辑,老師帶著我們一個(gè)一個(gè)需求的講解,對(duì)于復(fù)雜的需求和實(shí)現(xiàn)藻丢,老師會(huì)先給出一個(gè)與之相關(guān)但是比較基礎(chǔ)的需求或者實(shí)現(xiàn)剪撬,讓我們一步一步的學(xué)習(xí)。相比學(xué)之前的我悠反,現(xiàn)在的我可以有底氣的說(shuō)具體某個(gè)組件怎么用残黑,為什么這么用,同類(lèi)產(chǎn)品有哪些斋否,為什么選擇這個(gè)而不是其他的梨水,甚至部分原理源碼都可以說(shuō)出來(lái),每一個(gè)模塊的最后老師都會(huì)帶著我們深入底層原理去了解具體某一個(gè)功能的實(shí)現(xiàn)茵臭,也會(huì)帶著我們?nèi)テ饰鲈创a疫诽,看看源碼是怎樣寫(xiě)的!
2. 課程內(nèi)容
課程說(shuō)的再多也不如自己去看旦委,我給幾張知識(shí)思維導(dǎo)圖奇徒,看過(guò)就知道干貨有多少了!
教學(xué)服務(wù)
- 班主任每天催學(xué)習(xí)缨硝,提醒交作業(yè)逼龟,安排直播課,帶動(dòng)群里學(xué)習(xí)氣氛追葡,服務(wù)很周到
- 導(dǎo)師解答超級(jí)耐心,不會(huì)因?yàn)槟銌?wèn)的問(wèn)題有多簡(jiǎn)單或者稍微百度以下就能明白奕短,還會(huì)根據(jù)你問(wèn)的問(wèn)題宜肉,舉一反三,給你講一些相關(guān)的知識(shí)
- 關(guān)于作業(yè)翎碑,每一個(gè)知識(shí)點(diǎn)結(jié)束谬返,都會(huì)有小作業(yè),每一個(gè)模塊結(jié)束都會(huì)有一個(gè)大作業(yè)日杈,每一份作業(yè)導(dǎo)師都會(huì)批改遣铝,只有批改通過(guò)了才能學(xué)習(xí)接下來(lái)的內(nèi)容
內(nèi)推服務(wù)
群里已經(jīng)有好幾波內(nèi)推了,這個(gè)月還和京東合作莉擒,成立專屬內(nèi)推酿炸,解決就業(yè)問(wèn)題。而且投簡(jiǎn)歷之前涨冀,可以去找導(dǎo)師修改簡(jiǎn)歷填硕,讓你的簡(jiǎn)歷過(guò)關(guān)的機(jī)會(huì)更高,也會(huì)對(duì)你進(jìn)行面試前的指導(dǎo),簡(jiǎn)直貼心的不要不要扁眯!
個(gè)人的兩句話
自學(xué)固然可以壮莹,但是時(shí)間成本很高,而且知識(shí)并不系統(tǒng)姻檀,是時(shí)間成本更高還是培訓(xùn)費(fèi)成本更高命满,還有你一個(gè)人能否堅(jiān)持學(xué)習(xí),不受外界誘惑绣版?
對(duì)于拉勾胶台,我簡(jiǎn)而言之,豐富而完善的知識(shí)體系僵娃,行業(yè)大咖的直播解答概作,獨(dú)家的內(nèi)推資源,導(dǎo)師班主任全程伴讀默怨,在你偷懶的時(shí)候甩出小鞭子讯榕,定期測(cè)評(píng),完善的作業(yè)機(jī)制匙睹,良好的學(xué)習(xí)環(huán)境
下面正文開(kāi)始
一愚屁、HDFS概述
1. HDFS產(chǎn)出背景及定義
- HDFS產(chǎn)生背景
隨著數(shù)據(jù)量越來(lái)越大,在一個(gè)操作系統(tǒng)存不下所有的數(shù)據(jù)痕檬,那么就分配到更多的操作系統(tǒng)管理的磁盤(pán)中霎槐,但是不方便管理和維護(hù),迫切需要一種系統(tǒng)來(lái)管理多臺(tái)機(jī)器上的文件梦谜,這就是分布式文件管理系統(tǒng)丘跌。HDFS只是分布式文件管理系統(tǒng)中的一種。
-
HDFS定義
HDFS(Hadoop Distributed File System)唁桩,它是一個(gè)文件系統(tǒng)闭树,用于存儲(chǔ)文件,通過(guò)目錄樹(shù)來(lái)定位文件荒澡;其次报辱,它是分布式的,由很多服務(wù)器聯(lián)合起來(lái)實(shí)現(xiàn)其功能单山,集群中的服務(wù)器有各自的角色碍现,HDFS是分布式存儲(chǔ)服務(wù)。
HDFS的使用場(chǎng)景:適合一次寫(xiě)入米奸,多次讀出的場(chǎng)景昼接,且不支持文件的修改。適合用來(lái)做數(shù)據(jù)分析悴晰,并不適合用來(lái)做網(wǎng)盤(pán)應(yīng)用辩棒。
2. HDFS優(yōu)缺點(diǎn)
-
優(yōu)點(diǎn):
-
高容錯(cuò)性
數(shù)據(jù)自動(dòng)保存多個(gè)副本。它通過(guò)增加副本的形式,提高容錯(cuò)性一睁。
某一個(gè)副本丟失以后钻弄,它可以自動(dòng)恢復(fù)。
-
適合處理大數(shù)據(jù)
- 數(shù)據(jù)規(guī)模:能夠處理數(shù)據(jù)規(guī)模達(dá)到GB者吁、TB窘俺、甚至PB級(jí)別的數(shù)據(jù);
- 文件規(guī)模:能夠處理百萬(wàn)規(guī)模以上的文件數(shù)量复凳,數(shù)量相當(dāng)之大瘤泪。
-
可構(gòu)建在廉價(jià)機(jī)器上,通過(guò)多副本機(jī)制育八,提高可靠性对途。
?
-
-
缺點(diǎn):
不適合低延時(shí)數(shù)據(jù)訪問(wèn),比如毫秒級(jí)的存儲(chǔ)數(shù)據(jù)髓棋,是做不到的实檀。
-
無(wú)法高效的對(duì)大量小文件進(jìn)行存儲(chǔ)。
- 存儲(chǔ)大量小文件的話按声,它會(huì)占用NameNode大量的內(nèi)存來(lái)存儲(chǔ)文件目錄和塊信息膳犹。這樣是不可取的,因?yàn)镹ameNode的內(nèi)存總是有限的签则;
- 小文件存儲(chǔ)的尋址時(shí)間會(huì)超過(guò)讀取時(shí)間须床,它違反了HDFS的設(shè)計(jì)目標(biāo)。
-
不支持并發(fā)寫(xiě)入渐裂、文件隨機(jī)修改豺旬。
一個(gè)文件只能有一個(gè)寫(xiě),不允許多個(gè)線程同時(shí)寫(xiě)柒凉;
僅支持?jǐn)?shù)據(jù)append(追加)哈垢,不支持文件的隨機(jī)修改。
3. HDFS的重要概念
HDFS 通過(guò)統(tǒng)一的命名空間目錄樹(shù)來(lái)定位文件扛拨; 另外,它是分布式的举塔,由很多服務(wù)器?聯(lián)合起來(lái)實(shí)現(xiàn)其功能绑警,集群中的服務(wù)器?有各自的角色(分布式本質(zhì)是拆分,各司其職)
-
典型的 Master/Slave 架構(gòu)
- HDFS 的架構(gòu)是典型的 Master/Slave 結(jié)構(gòu)
- HDFS 集群往往是一個(gè) NameNode+多個(gè)DataNode 組成(HA架構(gòu)會(huì)有兩個(gè)NameNode央渣,聯(lián)邦機(jī)制)
- NameNode 是集群的主節(jié)點(diǎn)计盒,DataNode 是集群的從節(jié)點(diǎn)
-
分塊存儲(chǔ)(block機(jī)制)
- HDFS 中的文件在物理上是 分塊存儲(chǔ)(block)的,塊的大小可以通過(guò)配置參數(shù)來(lái)規(guī)定
- Hadoop2.x 版本中默認(rèn)的block大小是 128M芽丹,老版本默認(rèn)是64M
- 切分規(guī)則:如果有兩個(gè)文件北启,分別是 200M 和 20M,那么第一個(gè)文件先分成兩個(gè)切片(128M + 72M),第二個(gè)文件分成一個(gè)切片(20M)咕村,共三個(gè)切片
-
命名空間(NameSpace)
-
HDFS
支持傳統(tǒng)的層次型文件組織結(jié)構(gòu)场钉,用戶或者應(yīng)用程序可以創(chuàng)建目錄,然后將文件保存在這些目錄里懈涛。文件系統(tǒng)名字空間的層次結(jié)構(gòu)和大多數(shù)現(xiàn)有的文件系統(tǒng)類(lèi)似:用戶可以創(chuàng)建逛万、刪除、移動(dòng)或重命名文件
-
Namenode
負(fù)責(zé)維護(hù)文件系統(tǒng)的名字空間批钠,任何對(duì)文件系統(tǒng)名字空間或?qū)傩缘男薷亩紝⒈?Namenode 記錄下來(lái)
-
抽象目錄樹(shù)
HDFS 提供給客戶單一的一個(gè)抽象目錄樹(shù)宇植,用戶不知道這些文件是存儲(chǔ)在哪個(gè)dataNode上
訪問(wèn)形式:
hdfs://namenode的hostname:port/test/input
例如:
hdfs://linux121:9000/test/input
-
-
NameNode 元數(shù)據(jù)管理
- 我們把 目錄結(jié)構(gòu) 及 文件分塊位置信息 叫做元數(shù)據(jù)
- NameNode 的元數(shù)據(jù)記錄每一個(gè)文件所對(duì)應(yīng)的 block 信息(block的 id 以及所在的 DataNode 節(jié)點(diǎn)的信息)
-
DataNode 數(shù)據(jù)存儲(chǔ)
- 文件的各個(gè) block 的具體存儲(chǔ)管理由 DataNode 節(jié)點(diǎn)承擔(dān)
- 一個(gè) block 會(huì)有多個(gè) DataNode 來(lái)存儲(chǔ),DataNode 會(huì)定時(shí)向 NameNode 來(lái)匯報(bào)自己持有的 block 信息(<font color=red>這就是高容錯(cuò)的體現(xiàn)埋心,很重要</font>)
-
副本機(jī)制
為了容錯(cuò)指郁,文件的所有 block 都會(huì)有副本,默認(rèn)是 3 個(gè)(包括本來(lái)的block拷呆,一共 3 個(gè))闲坎。每個(gè)文件的 block大小 和 副本系數(shù) 都是可配置的
應(yīng)用程序可以指定某個(gè)文件的副本數(shù)目,副本系數(shù)可以在文件創(chuàng)建的時(shí)候指定洋腮,也可以在之后改變
如果副本數(shù)量設(shè)置為 10箫柳,但設(shè)備數(shù)只有 3臺(tái),那么不會(huì)真正創(chuàng)建 10 個(gè)副本啥供,而是創(chuàng)建相當(dāng)于設(shè)備數(shù)量的副本悯恍,即 3個(gè)副本。等設(shè)備數(shù)增加到 10 臺(tái)伙狐,創(chuàng)建的副本數(shù)才達(dá)到 10 臺(tái)(<font color=red>很重要</font>)
-
一次寫(xiě)入涮毫,多次讀出
- HDFS 是設(shè)計(jì)成適應(yīng) 一次寫(xiě)入,多次讀出 的場(chǎng)景贷屎,且不支持文件的隨機(jī)修改(支持追加寫(xiě)入罢防,不支持隨機(jī)更新)
- 因此,HDFS 適合用來(lái)做 大數(shù)據(jù)分析的底層存儲(chǔ)服務(wù)唉侄,并不適合用來(lái)做網(wǎng)盤(pán)等應(yīng)用(修改不方便咒吐,延遲大,網(wǎng)絡(luò)開(kāi)銷(xiāo)大属划,成本太高)
4. HDFS架構(gòu)
- NameNode: HDFS集群的管理者恬叹,Master
- 維護(hù)管理Hdfs的名稱空間(NameSpace)
- 維護(hù)副本策略
- 記錄?件塊(Block)的映射信息
- 負(fù)責(zé)處理客戶端讀寫(xiě)請(qǐng)求
-
DataNode: NameNode下達(dá)命令,DataNode執(zhí)行實(shí)際操作同眯,Slave節(jié)點(diǎn)绽昼。
保存實(shí)際的數(shù)據(jù)塊
負(fù)責(zé)數(shù)據(jù)塊的讀寫(xiě)
-
Client: 客戶端
- 上傳?文件到HDFS的時(shí)候,Client負(fù)責(zé)將?件切分成Block,然后進(jìn)行上傳
- 請(qǐng)求NameNode交互须蜗,獲取文件的位置信息
- 讀取或?qū)?文件硅确,與DataNode交互
- Client可以使?一些命令來(lái)管理HDFS或者訪問(wèn)HDFS
二目溉、 HDFS 客戶端操作
1. Shell命令行操作HDFS
-
基本語(yǔ)法
- bin/hadoop fs 具體命令
- bin/hdfs dfs 具體命令(<font color=red>推薦</font>)
-
命令?全
[root@linux121 hadoop-2.9.2]# bin/hdfs dfs Usage: hadoop fs [generic options] [-appendToFile <localsrc> ... <dst>] [-cat [-ignoreCrc] <src> ...] [-checksum <src> ...] [-chgrp [-R] GROUP PATH...] [-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...] [-chown [-R] [OWNER][:[GROUP]] PATH...] [-copyFromLocal [-f] [-p] [-l] [-d] <localsrc> ... <dst>] [-copyToLocal [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>] [-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] <path> ...] [-cp [-f] [-p | -p[topax]] [-d] <src> ... <dst>] [-createSnapshot <snapshotDir> [<snapshotName>]] [-deleteSnapshot <snapshotDir> <snapshotName>] [-df [-h] [<path> ...]] [-du [-s] [-h] [-x] <path> ...] [-expunge] [-find <path> ... <expression> ...] [-get [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>] [-getfacl [-R] <path>] [-getfattr [-R] {-n name | -d} [-e en] <path>] [-getmerge [-nl] [-skip-empty-file] <src> <localdst>] [-help [cmd ...]] [-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [<path> ...]] [-mkdir [-p] <path> ...] [-moveFromLocal <localsrc> ... <dst>] [-moveToLocal <src> <localdst>] [-mv <src> ... <dst>] [-put [-f] [-p] [-l] [-d] <localsrc> ... <dst>] [-renameSnapshot <snapshotDir> <oldName> <newName>] [-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ...] [-rmdir [--ignore-fail-on-non-empty] <dir> ...] [-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]] [-setfattr {-n name [-v value] | -x name} <path>] [-setrep [-R] [-w] <rep> <path> ...] [-stat [format] <path> ...] [-tail [-f] <file>] [-test -[defsz] <path>] [-text [-ignoreCrc] <src> ...] [-touchz <path> ...] [-truncate [-w] <length> <path> ...] [-usage [cmd ...]] Generic options supported are: -conf <configuration file> specify an application configuration file -D <property=value> define a value for a given property -fs <file:///|hdfs://namenode:port> specify default filesystem URL to use, overrides 'fs.defaultFS' property from configurations. -jt <local|resourcemanager:port> specify a ResourceManager -files <file1,...> specify a comma-separated list of files to be copied to the map reduce cluster -libjars <jar1,...> specify a comma-separated list of jar files to be included in the classpath -archives <archive1,...> specify a comma-separated list of archives to be unarchived on the compute machines
-
HDFS命令演示
-
首先啟動(dòng)Hadoop集群(HDFS和YARN要做各自的節(jié)點(diǎn)上啟動(dòng))
[root@linux121 hadoop-2.9.2]$ sbin/start-dfs.sh [root@linux122 hadoop-2.9.2]$ sbin/start-yarn.sh
-
-help:輸出這個(gè)命令參數(shù)
[root@linux121 hadoop-2.9.2]$ hdfs dfs -help rm
-
-ls: 顯示?錄信息
[root@linux121 hadoop-2.9.2]$ hdfs dfs -ls /
-
-mkdir: 在HDFS上創(chuàng)建目錄
[root@linux121 hadoop-2.9.2]$ hdfs dfs -mkdir -p /lagou/bigdata
-
-moveFromLocal: 從本地剪切粘貼到HDFS
[root@linux121 hadoop-2.9.2]$ touch hadoop.txt [root@linux121 hadoop-2.9.2]$ hdfs dfs -moveFromLocal ./hadoop.txt /lagou/bigdata
-
-appendToFile: 追加?個(gè)文件到已經(jīng)存在的?件末尾
[root@linux121 hadoop-2.9.2]$ touch hdfs.txt [root@linux121 hadoop-2.9.2]$ vi hdfs.txt 輸入 namenode datanode block replication [root@linux121 hadoop-2.9.2]$ hdfs dfs -appendToFile hdfs.txt /lagou/bigdata/hadoop.txt
-
-cat: 顯示文件內(nèi)容
[root@linux121 hadoop-2.9.2]$ hdfs dfs -cat /lagou/bigdata/hadoop.txt
-
-chgrp 、-chmod菱农、-chown: Linux?件系統(tǒng)中的?法一樣缭付,修改文件所屬權(quán)限
[root@linux121 hadoop-2.9.2]$ hdfs dfs -chmod 666 /lagou/bigdata/hadoop.txt [root@linux121 hadoop-2.9.2]$ hdfs dfs -chown root:root /lagou/bigdata/hadoop.txt
-
-copyFromLocal: 從本地?件系統(tǒng)中拷?文件到HDFS路徑去
[root@linux121 hadoop-2.9.2]$ hdfs dfs -copyFromLocal README.txt /
-
-copyToLocal: 從HDFS拷貝到本地
[root@linux121 hadoop-2.9.2]$ hdfs dfs -copyToLocal /lagou/bigdata/hadoop.txt ./
-
-cp : 從HDFS的?個(gè)路徑拷?到HDFS的另一個(gè)路徑
[root@linux121 hadoop-2.9.2]$ hdfs dfs -cp /lagou/bigdata/hadoop.txt /hdfs.txt
-
-mv: 在HDFS?錄中移動(dòng)文件
[root@linux121 hadoop-2.9.2]$ hdfs dfs -mv /hdfs.txt /lagou/bigdata/
-
-get: 等同于copyToLocal,就是從HDFS下載文件到本地
[root@linux121 hadoop-2.9.2]$ hdfs dfs -get /lagou/bigdata/hadoop.txt ./
-
-put: 等同于copyFromLocal
[root@linux121 hadoop-2.9.2]$ hdfs dfs -mkdir -p /user/root/test/ #本地?文件系統(tǒng)創(chuàng)建yarn.txt [root@linux121 hadoop-2.9.2]$ vim yarn.txt resourcemanager nodemanager [root@linux121 hadoop-2.9.2]$ hdfs dfs -put ./yarn.txt /user/root/test/
-
-tail: 顯示?個(gè)?件的末尾
[root@linux121 hadoop-2.9.2]$ hdfs dfs -tail /user/root/test/yarn.txt
-
-rm: 刪除?件或?件夾
[root@linux121 hadoop-2.9.2]$ hdfs dfs -rm /user/root/test/yarn.txt
-
-rmdir: 刪除空?錄
[root@linux121 hadoop-2.9.2]$ hdfs dfs -mkdir /test [root@linux121 hadoop-2.9.2]$ hdfs dfs -rmdir /test
-
-du: 統(tǒng)計(jì)?件夾的?小信息
[root@linux121 hadoop-2.9.2]$ hdfs dfs -du -s -h /user/root/test [root@linux121 hadoop-2.9.2]$ hdfs dfs -du -h /user/root/test
-
-setrep: 設(shè)置HDFS中?件的副本數(shù)量
[root@linux121 hadoop-2.9.2]$ hdfs dfs -setrep 10 /lagou/bigdata/hadoop.txt
-
2. JAVA客戶端
2.1 客戶端環(huán)境準(zhǔn)備
-
將Hadoop-2.9.2安裝包解壓到非中?路徑(例如:E:\hadoop-2.9.2)大莫。
-
配置HADOOP_HOME環(huán)境變量 image-20201130152417302.png
-
配置Path環(huán)境變量蛉腌。
創(chuàng)建?個(gè)Maven工程ClientDemo
-
導(dǎo)入相應(yīng)的依賴坐標(biāo)+日志配置文件
-
需要導(dǎo)入三個(gè)模塊:hadoop-common、hadoopclient只厘、hadoop-hdfs
<dependencies> <!-- 導(dǎo)入三個(gè)模塊:hadoop-common烙丛、hadoopclient、hadoop-hdfs --> <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common --> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.9.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoopclient --> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.9.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs --> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.9.2</version> </dependency> <!-- 單元測(cè)試 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> </dependency> <!-- 日志打印 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.8.2</version> </dependency> </dependencies>
-
為了便于控制程序運(yùn)行打印的日志數(shù)量羔味,需要在項(xiàng)目的
src/main/resources
目錄下河咽,新建一個(gè)文件,命名為log4j.properties
赋元,文件內(nèi)容如下:log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
-
創(chuàng)建包名:com.lagou.hdfs
-
創(chuàng)建HdfsClient類(lèi)
public class HdfsClient{ @Test public void testMkdirs() throws IOException, InterruptedException, URISyntaxException { // 1 獲取?件系統(tǒng) Configuration configuration = new Configuration(); // 配置在集群上運(yùn)行 // configuration.set("fs.defaultFS", "hdfs://linux121:9000"); // FileSystem fs = FileSystem.get(configuration); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 創(chuàng)建目錄 fs.mkdirs(new Path("/test")); // 3 關(guān)閉資源 fs.close(); } }
會(huì)遇到的問(wèn)題:
-
如果不指定操作 HDFS 集群的用戶信息忘蟹,默認(rèn)是 獲取當(dāng)前操作系統(tǒng)的用戶信息,出現(xiàn)權(quán)限被拒絕的問(wèn)題搁凸,報(bào)錯(cuò)如下:
出現(xiàn)問(wèn)題的原因:
由于 HDFS 的權(quán)限管理機(jī)制是:用戶告訴 hdfs 自己是什么用戶媚值,hdfs 都會(huì)相信,認(rèn)為用戶不會(huì)做壞事护糖。HDFS?件權(quán)限的目的褥芒,防?好?做錯(cuò)事,?不是阻?壞人做壞事嫡良。HDFS相信你告訴我你是誰(shuí)锰扶,你就是誰(shuí)。因此這種權(quán)限管理比較雞肋
解決辦法:
-
把 根目錄 的權(quán)限設(shè)置為 777 寝受,關(guān)于文件權(quán)限管理 交給其他軟件去做
hdfs dfs -R 777 /
-
在配置文件 hdfs-site.xml 中添加以下屬性坷牛,以關(guān)閉 HDFS 集群權(quán)限校驗(yàn),修改完成之后要分發(fā)到其它節(jié)點(diǎn)很澄,同時(shí)要重啟HDFS集群
vim hdfs-site.xml #添加如下屬性 <property> <name>dfs.permissions.enabled</name> <value>false</value> </property>
-
指定用戶信息獲取 FileSystem 對(duì)象
FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root")
-
windows 解壓安裝 Hadoop后京闰,在調(diào)用相關(guān)API操作 HDFS 集群時(shí)可能會(huì)報(bào)錯(cuò),如下圖: image-20201130153945039.png
出現(xiàn)問(wèn)題的原因:
這是由于 Hadoop 安裝缺少 windows 操作系統(tǒng)相關(guān)文件所致
解決辦法:
將 winutils.exe 拷貝到 windows 系統(tǒng) Hadoop 安裝目錄的 bin 目錄下即可
-
IDEA 啟動(dòng) Hadoop 的任務(wù)時(shí)甩苛,出現(xiàn)如下報(bào)錯(cuò):
解決辦法:
將 Hadoop.dll 文件 添加到 C:\Windows\System32 中
參數(shù)的優(yōu)先級(jí)
當(dāng)在配置文件蹂楣,java 代碼中,包括hdfs服務(wù)器的默認(rèn)配置浪藻,都設(shè)置副本數(shù)量時(shí),參數(shù)的優(yōu)先級(jí)是:
<font color=red>代碼中設(shè)置的值 -->用戶自定義配置文件 -->服務(wù)?的默認(rèn)配置</font>
2.2 HDFS的API操作
-
上傳文件
-
可通過(guò)
configuration.set("dfs.replication", "2")
設(shè)置副本數(shù)量@Test public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException { // 1 獲取?文件系統(tǒng) Configuration configuration = new Configuration(); configuration.set("dfs.replication", "2"); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2上傳?文件 fs.copyFromLocalFile(new Path("e:/lagou.txt"), new Path("/lagou.txt")); // 3 關(guān)閉資源 fs.close(); }
-
也可通過(guò) 配置文件
hdfs-site.xml
來(lái)指定乾翔,文件放在 resources 目錄下<font color=red>注:配置文件名 不能寫(xiě)錯(cuò)0施戴!</font>
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration>
-
-
下載文件
@Test public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException{ // 1 獲取?文件系統(tǒng) Configuration configuration = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 執(zhí)?行行下載操作 // boolean delSrc 指是否將原?文件刪除 // Path src 指要下載的?文件路路徑 // Path dst 指將?文件下載到的路路徑 // boolean useRawLocalFileSystem 是否開(kāi)啟?文件校驗(yàn) fs.copyToLocalFile(false, new Path("/lagou.txt"), newPath("e:/lagou_copy.txt"), true); // 3 關(guān)閉資源 fs.close(); }
-
刪除文件/文件夾
@Test public void testDelete() throws IOException, InterruptedException, URISyntaxException{ // 1 獲取?文件系統(tǒng) Configuration configuration = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 執(zhí)?行行刪除 fs.delete(new Path("/api_test/"), true); // 3 關(guān)閉資源 fs.close(); }
-
HDFS文件名更改
@Test public void testRename() throws IOException, InterruptedException, URISyntaxException{ // 1 獲取文件系統(tǒng) Configuration configuration = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 修改文件名稱 fs.rename(new Path("/banzhang.txt"), new Path("/banhua.txt")); // 3 關(guān)閉資源 fs.close(); }
-
查看 文件名稱、權(quán)限萌丈、長(zhǎng)度赞哗、塊信息
@Test public void testListFiles() throws IOException, InterruptedException, URISyntaxException{ // 1獲取?文件系統(tǒng) Configuration configuration = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 獲取?文件詳情 RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true); while(listFiles.hasNext()){ LocatedFileStatus status = listFiles.next(); // 輸出詳情 // ?文件名稱 System.out.println(status.getPath().getName()); // ?長(zhǎng)度 System.out.println(status.getLen()); // 權(quán)限 System.out.println(status.getPermission()); // 分組 System.out.println(status.getGroup()); // 獲取存儲(chǔ)的塊信息 BlockLocation[] blockLocations = status.getBlockLocations(); for (BlockLocation blockLocation : blockLocations) { // 獲取塊存儲(chǔ)的主機(jī)節(jié)點(diǎn) String[] hosts = blockLocation.getHosts(); for (String host : hosts) { System.out.println(host); } } System.out.println("-----------華麗的分割線----------"); } // 3 關(guān)閉資源 fs.close(); }
-
區(qū)分文件和文件夾
@Test public void testListStatus() throws IOException, InterruptedException, URISyntaxException{ // 1 獲取?文件配置信息 Configuration configuration = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 判斷是?文件還是?文件夾 FileStatus[] listStatus = fs.listStatus(new Path("/")); for (FileStatus fileStatus : listStatus) { // 如果是?文件 if (fileStatus.isFile()){ System.out.println("f:"+fileStatus.getPath().getName()); } else{ System.out.println("d:"+fileStatus.getPath().getName()); } } // 3 關(guān)閉資源 fs.close(); }
-
文件上傳 create
將本地文件上傳到 hdfs 上
@Test public void putFileToHDFS() throws IOException, InterruptedException, URISyntaxException { // 1 獲取文件系統(tǒng) Configuration configuration = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 創(chuàng)建輸?流 FileInputStream fis = new FileInputStream(new File("e:/lagou.txt")); // 3 獲取輸出流 FSDataOutputStream fos = fs.create(new Path("/lagou_io.txt")); // 4 流的拷貝 IOUtils.copyBytes(fis, fos, configuration); // 5 關(guān)閉資源(這里其實(shí)不需要關(guān)閉) IOUtils.closeStream(fos); IOUtils.closeStream(fis); fs.close(); }
-
文件下載 open
將 hdfs 文件下載到本地
@Test public void getFileFromHDFS() throws IOException, InterruptedException, URISyntaxException{ // 1 獲取?文件系統(tǒng) Configuration configuration = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 獲取輸?入流 FSDataInputStream fis = fs.open(new Path("/lagou_io.txt")); // 3 獲取輸出流 FileOutputStream fos = new FileOutputStream(new File("e:/lagou_io_copy.txt")); // 4 流的對(duì)拷 IOUtils.copyBytes(fis, fos, configuration); // 5 關(guān)閉資源 IOUtils.closeStream(fos); IOUtils.closeStream(fis); fs.close(); }
-
定位讀取 seek
將 HDFS上 的 lagou.txt 的內(nèi)容在控制臺(tái)輸出兩次
@Test public void readFileSeek2() throws IOException, InterruptedException, URISyntaxException{ // 1 獲取?文件系統(tǒng) Configuration configuration = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://linux121:9000"), configuration, "root"); // 2 打開(kāi)輸?入流,讀取數(shù)據(jù)輸出到控制臺(tái) FSDataInputStream in = null; try{ in = fs.open(new Path("/lagou.txt")); IOUtils.copyBytes(in, System.out, 4096, false); //從頭再次讀取,偏移量為0 表示從頭讀起 in.seek(0); IOUtils.copyBytes(in, System.out, 4096, false); }finally { IOUtils.closeStream(in); fs.close(); } }
三辆雾、 HDFS讀寫(xiě)解析
1. HDFS讀數(shù)據(jù)流程
HDFS讀數(shù)據(jù)流程:
- 客戶端通過(guò)Distributed FileSystem向NameNode請(qǐng)求下載文件肪笋,NameNode通過(guò)查詢?cè)獢?shù)據(jù),找到文件塊所在的DataNode地址度迂。
- 挑選一臺(tái)DataNode(就近原則藤乙,然后隨機(jī))服務(wù)器,請(qǐng)求讀取數(shù)據(jù)惭墓。
- DataNode開(kāi)始傳輸數(shù)據(jù)給客戶端(從磁盤(pán)里面讀取數(shù)據(jù)輸入流坛梁,以Packet(64KB)為單位來(lái)做校驗(yàn))。
- 客戶端以Packet為單位接收腊凶,先在本地緩存划咐,然后寫(xiě)入目標(biāo)文件。
2.HDFS寫(xiě)數(shù)據(jù)流程
HDFS寫(xiě)數(shù)據(jù)流程:
- 客戶端通過(guò)Distributed FileSystem模塊向NameNode請(qǐng)求上傳文件钧萍,NameNode檢查目標(biāo)文件是否已存在褐缠,父目錄是否存在。
- NameNode返回是否可以上傳风瘦。
- 客戶端請(qǐng)求第一個(gè) Block上傳到哪幾個(gè)DataNode服務(wù)器上队魏。
- NameNode返回3個(gè)DataNode節(jié)點(diǎn),分別為dn1弛秋、dn2器躏、dn3。
- 客戶端通過(guò)FSDataOutputStream模塊請(qǐng)求dn1上傳數(shù)據(jù)蟹略,dn1收到請(qǐng)求會(huì)繼續(xù)調(diào)用dn2登失,然后dn2調(diào)用dn3,將這個(gè)通信管道建立完成挖炬。
- dn1揽浙、dn2、dn3逐級(jí)應(yīng)答客戶端意敛。
- 客戶端開(kāi)始往dn1上傳第一個(gè)Block(先從磁盤(pán)讀取數(shù)據(jù)放到一個(gè)本地內(nèi)存緩存)馅巷,以Packet(64KB)為單位,dn1收到一個(gè)Packet就會(huì)傳給dn2草姻,dn2傳給dn3钓猬;dn1每傳一個(gè)packet會(huì)放入一個(gè)應(yīng)答隊(duì)列等待應(yīng)答。
- 當(dāng)一個(gè)Block傳輸完成之后撩独,客戶端再次請(qǐng)求NameNode上傳第二個(gè)Block的服務(wù)器敞曹。(重復(fù)執(zhí)行3-7步)账月。
驗(yàn)證Packet代碼:
@Test public void testUploadPacket() throws IOException { //1 準(zhǔn)備讀取本地文件的輸入流 final FileInputStream in = new FileInputStream(new File("e:/lagou.txt")); //2 準(zhǔn)備好寫(xiě)出數(shù)據(jù)到hdfs的輸出流 final FSDataOutputStream out = fs.create(new Path("/lagou.txt"), new Progressable() { public void progress() { //這個(gè)progress?法就是每傳輸64KB(packet)就會(huì)執(zhí)行一次 System.out.println("&"); } }); //3 實(shí)現(xiàn)流拷貝 IOUtils.copyBytes(in, out, configuration); //默認(rèn)關(guān)閉流選項(xiàng)是true,所以會(huì)?動(dòng)關(guān)閉 //4 關(guān)流 可以再次關(guān)閉也可以不關(guān)了 }
四澳迫、 NameNode和SecondaryNameNode
1. NN和2NN工作機(jī)制
問(wèn)題引出: NameNode如何管理和存儲(chǔ)元數(shù)據(jù)?
計(jì)算機(jī)中存儲(chǔ)數(shù)據(jù)的兩種方式:磁盤(pán)局齿、內(nèi)存
- 元數(shù)據(jù)存儲(chǔ)磁盤(pán):存儲(chǔ)磁盤(pán)?法?對(duì)客戶端對(duì)元數(shù)據(jù)信息的隨機(jī)訪問(wèn),還有響應(yīng)客戶請(qǐng)求橄登,必然是效率過(guò)低抓歼。但是安全性?
- 元數(shù)據(jù)存儲(chǔ)內(nèi)存:元數(shù)據(jù)存放內(nèi)存,可以高效的查詢以及快速響應(yīng)客戶端的查詢請(qǐng)求拢锹,數(shù)據(jù)保存在內(nèi)存谣妻,如果斷點(diǎn),內(nèi)存中的數(shù)據(jù)全部丟失面褐。安全性低
解決辦法: 內(nèi)存+磁盤(pán);NameNode內(nèi)存+FsImage的?件(磁盤(pán))
新問(wèn)題: 磁盤(pán)和內(nèi)存中元數(shù)據(jù)如何劃分?
兩個(gè)數(shù)據(jù)一模?樣拌禾,還是兩個(gè)數(shù)據(jù)合并到一起才是?份完整的數(shù)據(jù)呢?
- 如果兩份數(shù)據(jù)一模一樣的話,客戶端 Client 如果對(duì)元數(shù)據(jù)進(jìn)行增刪改操作展哭,則需要時(shí)刻保證兩份數(shù)據(jù)的一致性湃窍,導(dǎo)致效率變低
- 如果兩份數(shù)據(jù)合并后 ==> 完整數(shù)據(jù)的情況。NameNode 引入了 edits 文件(日志文件匪傍,只能追加寫(xiě)入)您市,記錄了client 的增刪改操作,而不再讓 NameNode 把數(shù)據(jù) dump 出來(lái)形成 fsimage文件(讓 NameNode 專注于處理客戶端的請(qǐng)求)
- edits文件:文件生成快役衡,恢復(fù)慢茵休;fsimage文件:文件生成慢,恢復(fù)快
新問(wèn)題: 誰(shuí)來(lái)負(fù)責(zé)文件合并手蝎?
如果長(zhǎng)時(shí)間添加數(shù)據(jù)到Edits中榕莺,會(huì)導(dǎo)致該文件數(shù)據(jù)過(guò)大,效率降低棵介,而且一旦斷電钉鸯,恢復(fù)元數(shù)據(jù)需要的時(shí)間過(guò)長(zhǎng)。因此邮辽,需要定期進(jìn)行FsImage和Edits的合并唠雕,但是誰(shuí)來(lái)合并?
- NameNode:NameNode本身任務(wù)重吨述,再負(fù)責(zé)合并岩睁,勢(shì)必效率過(guò)低王凑,甚至?xí)绊懕旧淼娜蝿?wù)
- 因此撒穷,引入一個(gè)新的節(jié)點(diǎn)SecondaryNamenode,專門(mén)用于FsImage和Edits的合并龙致。
流程分析:
-
第一階段:NameNode啟動(dòng)
- 第一次啟動(dòng)NameNode格式化后邓夕,創(chuàng)建Fsimage和Edits文件刘莹。如果不是第一次啟動(dòng)亿笤,直接加載編輯日志和鏡像文件到內(nèi)存。
- 客戶端對(duì)元數(shù)據(jù)進(jìn)行增刪改的請(qǐng)求栋猖。
- NameNode記錄操作日志,更新滾動(dòng)日志(所謂滾動(dòng)日志汪榔,即 把前一階段的日志保存成一個(gè)日志文件蒲拉,再新生成一個(gè)文件,新生成文件后綴帶有 inprogress 字樣)痴腌。
- NameNode在內(nèi)存中對(duì)數(shù)據(jù)進(jìn)行增刪改雌团。
-
第二階段:Secondary NameNode工作
- Secondary NameNode詢問(wèn)NameNode是否需要CheckPoint。直接帶回NameNode是否檢查結(jié)果士聪。
- Secondary NameNode請(qǐng)求執(zhí)行CheckPoint锦援。
- NameNode滾動(dòng)正在寫(xiě)的Edits日志。
- 將滾動(dòng)前的編輯日志和鏡像文件拷貝到Secondary NameNode剥悟。
- Secondary NameNode加載編輯日志和鏡像文件到內(nèi)存灵寺,并合并。
- 生成新的鏡像文件fsimage.chkpoint区岗。
- 拷貝fsimage.chkpoint到NameNode略板。
- NameNode將fsimage.chkpoint重新命名成fsimage。
<font color=red>NN和2NN工作機(jī)制詳解:</font>
Fsimage:NameNode內(nèi)存中元數(shù)據(jù)序列化后形成的文件慈缔。
Edits:記錄客戶端更新元數(shù)據(jù)信息的每一步操作(可通過(guò)Edits運(yùn)算出元數(shù)據(jù))叮称。
NameNode啟動(dòng)時(shí),先滾動(dòng)Edits并生成一個(gè)空的edits.inprogress藐鹤,然后加載Edits和Fsimage到內(nèi)存中瓤檐,此時(shí)NameNode內(nèi)存就持有最新的元數(shù)據(jù)信息。Client開(kāi)始對(duì)NameNode發(fā)送元數(shù)據(jù)的增刪改的請(qǐng)求娱节,這些請(qǐng)求的操作首先會(huì)被記錄到edits.inprogress中(查詢?cè)獢?shù)據(jù)的操作不會(huì)被記錄在Edits中挠蛉,因?yàn)椴樵儾僮鞑粫?huì)更改元數(shù)據(jù)信息),如果此時(shí)NameNode掛掉括堤,重啟后會(huì)從Edits中讀取元數(shù)據(jù)的信息碌秸。然后,NameNode會(huì)在內(nèi)存中執(zhí)行元數(shù)據(jù)的增刪改的操作悄窃。
由于Edits中記錄的操作會(huì)越來(lái)越多讥电,Edits文件會(huì)越來(lái)越大,導(dǎo)致NameNode在啟動(dòng)加載Edits時(shí)會(huì)很慢轧抗,所以需要對(duì)Edits和Fsimage進(jìn)行合并(所謂合并恩敌,就是將Edits和Fsimage加載到內(nèi)存中,照著Edits中的操作一步步執(zhí)行横媚,最終形成新的Fsimage)纠炮。SecondaryNameNode的作用就是幫助NameNode進(jìn)行Edits和Fsimage的合并工作月趟。
SecondaryNameNode首先會(huì)詢問(wèn)NameNode是否需要CheckPoint(觸發(fā)CheckPoint需要滿足兩個(gè)條件中的任意一個(gè),定時(shí)時(shí)間到和Edits中數(shù)據(jù)寫(xiě)滿了)恢口。直接帶回NameNode是否檢查結(jié)果孝宗。SecondaryNameNode執(zhí)行CheckPoint操作,首先會(huì)讓NameNode滾動(dòng)Edits并生成一個(gè)空的edits.inprogress耕肩,滾動(dòng)Edits的目的是給Edits打個(gè)標(biāo)記因妇,以后所有新的操作都寫(xiě)入edits.inprogress,其他未合并的Edits和Fsimage會(huì)拷貝到SecondaryNameNode的本地猿诸,然后將拷貝的Edits和Fsimage加載到內(nèi)存中進(jìn)行合并婚被,生成fsimage.chkpoint,然后將fsimage.chkpoint拷貝給NameNode梳虽,重命名為Fsimage后替換掉原來(lái)的Fsimage址芯。NameNode在啟動(dòng)時(shí)就只需要加載之前未合并的Edits和Fsimage即可,因?yàn)楹喜⑦^(guò)的Edits中的元數(shù)據(jù)信息已經(jīng)被記錄在Fsimage中窜觉。
2. Fsimage和Edits解析
-
NameNode在執(zhí)行格式化之后谷炸,會(huì)在/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name/current?錄下產(chǎn)?如下文件
- Fsimage?件: 是namenode中關(guān)于元數(shù)據(jù)的鏡像,一般稱為檢查點(diǎn)禀挫,這里包含了HDFS?件系統(tǒng)所有?錄以及?件相關(guān)信息(Block數(shù)量淑廊,副本數(shù)量,權(quán)限等信息)
- Edits文件 : 存儲(chǔ)了客戶端對(duì)HDFS文件系統(tǒng)所有的更新操作記錄特咆,Client對(duì)HDFS?件系統(tǒng)所有的更新操作都會(huì)被記錄到Edits?件中(不包括查詢操作)
- seen_txid: 該?件是保存了一個(gè)數(shù)字季惩,數(shù)字對(duì)應(yīng)著最后一個(gè)Edits?件名的數(shù)字
- VERSION: 該?件記錄namenode的一些版本號(hào)信息,比如:CusterId,namespaceID等
NameNode啟動(dòng)時(shí)會(huì)將Fsimage?件加載到內(nèi)存中腻格,同時(shí)也把之前未合并元數(shù)據(jù)的Edits?件加載画拾,集合兩個(gè)文件中的元數(shù)據(jù)這樣保證了NameNode中的元數(shù)據(jù)是最新最全的。通俗點(diǎn)說(shuō)就是NameNode啟動(dòng)時(shí)把Fsimage和Edits?件進(jìn)?了合并菜职。
2.1 Fsimage?件內(nèi)容
官方地址:
https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-hdfs/HdfsImageViewer.html
-
查看oiv和oev命令
[[root@linux121 current]$ hdfs oiv apply the offline fsimage viewer to an fsimage oev apply the offline edits viewer to an edits file
-
基本語(yǔ)法
hdfs oiv -p 文件類(lèi)型 -i鏡像文件 -o 轉(zhuǎn)換后文件輸出路徑
-
案例實(shí)操
[root@linux121 current]$ cd /opt/lagou/servers/hadoop2.9.2/data/tmp/dfs/name/current [root@linux121 current]$ hdfs oiv -p XML -i fsimage_0000000000000000265 -o /opt/lagou/servers/fsimage.xml [root@linux121 current]$ cat /opt/lagou/servers/fsimage.xml
-
查看文件
<?xml version="1.0"?> <fsimage> <version> <layoutVersion>-63</layoutVersion> <onDiskVersion>1</onDiskVersion> <oivRevision>826afbeae31ca687bc2f8471dc841b66ed2c6704</oivRevision> </version> <NameSection> <namespaceId>722925838</namespaceId> <genstampV1>1000</genstampV1> <genstampV2>1049</genstampV2> <genstampV1Limit>0</genstampV1Limit> <lastAllocatedBlockId>1073741873</lastAllocatedBlockId> <txid>621</txid> </NameSection> <INodeSection> <lastInodeId>16487</lastInodeId> <numInodes>36</numInodes> <inode> <id>16385</id> <type>DIRECTORY</type> <name></name> <mtime>1604115316122</mtime> <permission>root:supergroup:0777</permission> <nsquota>9223372036854775807</nsquota> <dsquota>-1</dsquota> </inode> <inode> <id>16389</id> <type>DIRECTORY</type> <name>wcinput</name> <mtime>1604023034981</mtime> <permission>root:supergroup:0777</permission> <nsquota>-1</nsquota> <dsquota>-1</dsquota> </inode> </INodeSection> </fsimage>
問(wèn)題: Fsimage 中為什么沒(méi)有記錄塊所對(duì)應(yīng) DataNode 青抛?
答案:在集群?jiǎn)?dòng)后,NameNode 要求 DataNode 上報(bào)數(shù)據(jù)塊信息酬核,并間隔一段時(shí)間后再次上報(bào)
2.2 Edits文件內(nèi)容
-
基本語(yǔ)法
hdfs oev -p 文件類(lèi)型 -i編輯日志 -o 轉(zhuǎn)換后文件輸出路徑
-
案例實(shí)操
[root@linux121 current]$ hdfs oev -p XML -i edits_0000000000000000266-0000000000000000267 -o /opt/lagou/servers/hadoop-2.9.2/edits.xml [root@linux121 current]$ cat /opt/lagou/servers/hadoop-2.9.2/edits.xml
-
查看文件
<?xml version="1.0" encoding="utf-8"?> <EDITS> <EDITS_VERSION>-63</EDITS_VERSION> <RECORD> <OPCODE>OP_START_LOG_SEGMENT</OPCODE> <DATA> <TXID>113</TXID> </DATA> </RECORD> <RECORD> <OPCODE>OP_SET_PERMISSIONS</OPCODE> <DATA> <TXID>114</TXID> <SRC>/wcoutput/_SUCCESS</SRC> <MODE>493</MODE> </DATA> </RECORD> <RECORD> <OPCODE>OP_SET_PERMISSIONS</OPCODE> <DATA> <TXID>115</TXID> <SRC>/wcoutput/part-r-00000</SRC> <MODE>493</MODE> </DATA> </RECORD> </EDITS> ...
備注:Edits中只記錄了更新相關(guān)的操作蜜另,查詢或者下載文件并不會(huì)記錄在內(nèi)!!
問(wèn)題: NameNode啟動(dòng)時(shí)如何確定加載哪些Edits?件呢?
答案: 需要借助fsimage?件最后數(shù)字編碼,來(lái)確定哪些edits之前是沒(méi)有合并到fsimage中嫡意,啟動(dòng)時(shí)只需要加載那些未合并的edits?件即可举瑰。
3. checkpoint周期
-
通常情況下,SecondaryNameNode每隔一小時(shí)執(zhí)行一次蔬螟。
官方默認(rèn)配置文件:
hdfs-default.xml
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>
-
一分鐘檢查一次操作次數(shù)此迅,3當(dāng)操作次數(shù)達(dá)到1百萬(wàn)時(shí),SecondaryNameNode執(zhí)行一次。
<property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description>操作動(dòng)作次數(shù)</description> </property> <property> <name>dfs.namenode.checkpoint.check.period</name> <value>60</value> <description> 1分鐘檢查一次操作次數(shù)</description> </property >
4. NameNode故障處理
NameNode故障后耸序,HDFS集群就無(wú)法正常工作忍些,因?yàn)镠DFS文件系統(tǒng)的元數(shù)據(jù)需要由NameNode來(lái)管理維護(hù)并與Client交互,如果元數(shù)據(jù)出現(xiàn)損壞和丟失同樣會(huì)導(dǎo)致NameNode?法正常?作進(jìn)?HDFS?件系統(tǒng)?法正常對(duì)外提供服務(wù)坎怪。
如果元數(shù)據(jù)出現(xiàn)丟失損壞如何恢復(fù)呢?
搭建HDFS的HA(?可用)集群罢坝,解決NN的單點(diǎn)故障問(wèn)題!!(借助Zookeeper實(shí)現(xiàn)HA,一個(gè) Active的NameNode,一個(gè)是Standby的NameNode)
-
將SecondaryNameNode中數(shù)據(jù)拷貝到NameNode存儲(chǔ)數(shù)據(jù)的目錄
kill -9 NameNode進(jìn)程
-
刪除NameNode存儲(chǔ)的數(shù)據(jù)(/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name)
[root@linux121 hadoop-2.9.2]rm -rf /opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name/*
-
拷貝SecondaryNameNode中數(shù)據(jù)到原NameNode存儲(chǔ)數(shù)據(jù)目錄
[root@linux121 hadoop-2.9.2]$ scp -r atguigu@hadoop104:/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/namesecondary/* ./name/
重新啟動(dòng)NameNode
[root@linux121 hadoop-2.9.2]$ sbin/hadoop-daemon.sh start namenode
-
使用-importCheckpoint選項(xiàng)啟動(dòng)NameNode守護(hù)進(jìn)程搅窿,從而將SecondaryNameNode中數(shù)據(jù)拷貝到NameNode目錄中炸客。
-
修改hdfs-site.xml中的
<property> <name>dfs.namenode.checkpoint.period</name> <value>120</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name</value> </property>
kill -9 NameNode進(jìn)程
-
刪除NameNode存儲(chǔ)的數(shù)據(jù)(/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name)
[root@linux121 hadoop-2.9.2]rm -rf /opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/name/*
-
如果SecondaryNameNode不和NameNode在一個(gè)主機(jī)節(jié)點(diǎn)上,需要將SecondaryNameNode存儲(chǔ)數(shù)據(jù)的目錄拷貝到NameNode存儲(chǔ)數(shù)據(jù)的平級(jí)目錄戈钢,并刪除in_use.lock文件
[root@linux123 dfs]$ scp -r root@linux121:/opt/lagou/servers/hadoop-2.9.2/data/tmp/dfs/namesecondary ./ [root@linux123 namesecondary]$ rm -rf in_use.lock [root@linux123 dfs]$ pwd /opt/lagou/servers/hadoop-2.9.2//data/tmp/dfs [root@linux123 dfs]$ ls data name namesecondary
-
導(dǎo)入檢查點(diǎn)數(shù)據(jù)(等待一會(huì)ctrl+c結(jié)束掉)
[root@linux121 hadoop-2.9.2]$ bin/hdfs namenode -importCheckpoint
-
啟動(dòng)NameNode
[root@linux121 hadoop-2.9.2]$ sbin/hadoop-daemon.sh start namenode
-
五、Hadoop的限額與歸檔以及集群安全模式
1. HDFS?件限額配置
HDFS文件的限額配置允許我們以?件?小或者文件個(gè)數(shù)來(lái)限制我們?cè)谀硞€(gè)目錄下上傳的文件數(shù)量或者文件內(nèi)容總量是尔,以便達(dá)到我們類(lèi)似百度網(wǎng)盤(pán)等限制每個(gè)?戶允許上傳的最大的?件的量
-
數(shù)量限額
#創(chuàng)建hdfs?件夾 hdfs dfs -mkdir -p /user/root/lagou # 給該?件夾下?設(shè)置最多上傳兩個(gè)文件殉了,上傳?件,發(fā)現(xiàn)只能上傳一個(gè)文件 hdfs dfsadmin -setQuota 2 /user/root/lagou # 清除文件數(shù)量限制 hdfs dfsadmin -clrQuota /user/root/lagou
-
空間?小限額
# 限制空間?小4KB hdfs dfsadmin -setSpaceQuota 4k /user/root/lagou #上傳超過(guò)4Kb的?件?小上去提示文件超過(guò)限額 hdfs dfs -put /export/softwares/xxx.tar.gz /user/root/lagou #清除空間限額 hdfs dfsadmin -clrSpaceQuota /user/root/lagou #查看hdfs?件限額數(shù)量 hdfs dfs -count -q -h /user/root/lagou
2. HDFS的安全模式
- 安全模式是HDFS所處的一種特殊狀態(tài)拟枚,在這種狀態(tài)下薪铜,<font color=red>文件系統(tǒng)只接受讀數(shù)據(jù)請(qǐng)求,而不接受刪除恩溅、修改等變更請(qǐng)求</font>隔箍。在NameNode主節(jié)點(diǎn)啟動(dòng)時(shí),HDFS?先進(jìn)入安全模式脚乡,DataNode在啟動(dòng)的時(shí)候會(huì)向NameNode匯報(bào)可用的block等狀態(tài)蜒滩,當(dāng)整個(gè)系統(tǒng)達(dá)到安全標(biāo)準(zhǔn)時(shí),HDFS自動(dòng)離開(kāi)安全模式奶稠。如果HDFS出于安全模式下俯艰,則文件block不能進(jìn)行任何的副本復(fù)制操作,因此達(dá)到最?的副本數(shù)量要求是基于DataNode啟動(dòng)時(shí)的狀態(tài)來(lái)判定的锌订,啟動(dòng)時(shí)不會(huì)再做任何復(fù)制(從?達(dá)到最?副本數(shù)量要求)竹握,HDFS集群剛啟動(dòng)的時(shí)候,默認(rèn)30S鐘的時(shí)間是出于安全期的辆飘,只有過(guò)了30S之后啦辐,集群脫離了了安全期,然后才可以對(duì)集群進(jìn)行操作蜈项。
- 相關(guān)命令:
hdfs dfsadmin -safemode
3. Hadoop歸檔技術(shù)
-
主要解決HDFS集群存在?量?文件的問(wèn)題!!
由于?量?文件會(huì)占?NameNode的內(nèi)存芹关,因此對(duì)于HDFS來(lái)說(shuō)存儲(chǔ)?量?文件造成NameNode內(nèi)存資源的浪費(fèi)!
-
Hadoop存檔?件HAR文件,是?個(gè)更高效的文件存檔工具紧卒,HAR?件是由?組文件通過(guò)archive?具創(chuàng)建?來(lái)充边,在減少了NameNode的內(nèi)存使?的同時(shí),可以對(duì)文件進(jìn)行透明的訪問(wèn),通俗來(lái)說(shuō)就是HAR?件對(duì)NameNode來(lái)說(shuō)是?個(gè)?件減少了內(nèi)存的浪費(fèi)浇冰,對(duì)于實(shí)際操作處理文件依然是一個(gè)?個(gè)獨(dú)立的文件贬媒。
-
案例
-
啟動(dòng)YARN集群
[root@linux121 hadoop-2.9.2]$ start-yarn.sh
-
歸檔文件
把/user/lagou/input?錄?面的所有?件歸檔成?個(gè)叫input.har的歸檔?件,并把歸檔后文件存儲(chǔ)到/user/lagou/output路徑下肘习。
[root@linux121 hadoop-2.9.2]$ bin/hadoop archive -archiveName input.har –p /user/root/input /user/root/output
-
查看歸檔
[root@linux121 hadoop-2.9.2]$ hadoop fs -lsr /user/root/output/input.har [root@linux121 hadoop-2.9.2]$ hadoop fs -lsr har:///user/root/output/input.har
-
解歸檔?件
[root@linux121 hadoop-2.9.2]$ hadoop fs -cp har:///user/root/output/input.har/* /user/root
-
六际乘、DataNode
1. DataNode工作機(jī)制
DataNode工作機(jī)制:
- 一個(gè)數(shù)據(jù)塊在DataNode上以文件形式存儲(chǔ)在磁盤(pán)上,包括兩個(gè)文件漂佩,一個(gè)是數(shù)據(jù)本身脖含,一個(gè)是元數(shù)據(jù)包括數(shù)據(jù)塊的長(zhǎng)度,塊數(shù)據(jù)的校驗(yàn)和投蝉,以及時(shí)間戳养葵。
- DataNode啟動(dòng)后向NameNode注冊(cè),通過(guò)后瘩缆,周期性(1小時(shí))的向NameNode上報(bào)所有的塊信息关拒。
- 心跳是每3秒一次,心跳返回結(jié)果帶有NameNode給該DataNode的命令如復(fù)制塊數(shù)據(jù)到另一臺(tái)機(jī)器庸娱,或刪除某個(gè)數(shù)據(jù)塊着绊。如果超過(guò)10分鐘沒(méi)有收到某個(gè)DataNode的心跳,則認(rèn)為該節(jié)點(diǎn)不可用熟尉。
- 集群運(yùn)行中可以安全加入和退出一些機(jī)器归露。
2. 數(shù)據(jù)完整性
-
思考:
如果電腦磁盤(pán)里面存儲(chǔ)的數(shù)據(jù)是控制高鐵信號(hào)燈的紅燈信號(hào)(1)和綠燈信號(hào)(0),但是存儲(chǔ)該數(shù)據(jù)的磁盤(pán)壞了斤儿,一直顯示是綠燈剧包,是否很危險(xiǎn)?同理DataNode節(jié)點(diǎn)上的數(shù)據(jù)損壞了往果,卻沒(méi)有發(fā)現(xiàn)玄捕,是否也很危險(xiǎn),那么如何解決呢棚放?
-
DataNode節(jié)點(diǎn)保證數(shù)據(jù)完整性的方法:
- 當(dāng)DataNode讀取Block的時(shí)候枚粘,它會(huì)計(jì)算CheckSum。
- 如果計(jì)算后的CheckSum飘蚯,與Block創(chuàng)建時(shí)值不一樣馍迄,說(shuō)明Block已經(jīng)損壞。
- Client讀取其他DataNode上的Block局骤。
-
DataNode在其文件創(chuàng)建后周期驗(yàn)證CheckSum攀圈,如下圖所示。 image-20201130182018827.png
3. 掉線時(shí)限參數(shù)設(shè)置
DataNode進(jìn)程死亡或者網(wǎng)絡(luò)故障造成DataNode無(wú)法與NameNode通信
NameNode不會(huì)立即把該節(jié)點(diǎn)判定為死亡峦甩,要經(jīng)過(guò)一段時(shí)間赘来,這段時(shí)間暫稱作超時(shí)時(shí)長(zhǎng)现喳。
HDFS默認(rèn)的超時(shí)時(shí)長(zhǎng)為10分鐘+30秒。
-
如果定義超時(shí)時(shí)間為T(mén)imeOut犬辰,則超時(shí)時(shí)長(zhǎng)的計(jì)算公式為:
TimeOut = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval嗦篱。 而默認(rèn)的dfs.namenode.heartbeat.recheck-interval 大小為5分鐘,dfs.heartbeat.interval默認(rèn)為3秒幌缝。
注意:
hdfs-site.xml 配置文件中的heartbeat.recheck.interval的單位為<font color=red>毫秒</font>灸促,dfs.heartbeat.interval的單位為<font color=red>秒</font>。
<property> <name>dfs.namenode.heartbeat.recheck-interval</name> <value>300000</value> </property> <property> <name>dfs.heartbeat.interval</name> <value>3</value> </property>
對(duì)大數(shù)據(jù)感興趣的小伙伴可以關(guān)注我的公眾號(hào):大數(shù)據(jù)學(xué)習(xí)寶典涵卵,在上面會(huì)定期更新學(xué)習(xí)筆記和一些心得浴栽!