前言
初學(xué)hadoop,網(wǎng)上的相關(guān)資料很多,講解大同小異:一堆專業(yè)術(shù)語(yǔ)+火星文
學(xué)習(xí)起來很困難悟狱,很難探究出它的存在意義膨报,因此本文結(jié)合自己的理解磷籍,用地球人的語(yǔ)言來描述hadoop
HADOOP
hadoop解決的是海量數(shù)據(jù)的存儲(chǔ)和計(jì)算問題,為什么會(huì)有這種問題现柠?
因?yàn)楝F(xiàn)在是一個(gè)信息爆炸的時(shí)代院领,數(shù)據(jù)量大到的一臺(tái)電腦硬盤存不下,且這么大的數(shù)據(jù)量在數(shù)據(jù)匯總計(jì)算時(shí)一臺(tái)電腦又算不過來
hadoop怎么解決這個(gè)問題吶够吩,就在于其提供的三大核心HDFS
,YARN
,MAPREDUCE
比然,其中HDFS
用來解決大文件的存儲(chǔ)難題,YARN
用于解決大文件的計(jì)算難題周循,MAPREDUCE
是一種具體的計(jì)算方式
HDFS
概念
HDFS可以說是一個(gè)hadoop下獨(dú)立的產(chǎn)品强法,可以單獨(dú)運(yùn)行
HDFS主要是用來解決大文件的存儲(chǔ),對(duì)應(yīng)痛點(diǎn)是大數(shù)據(jù)文件的存儲(chǔ)一臺(tái)電腦硬盤有限存不下鱼鼓,先拋開HDFS拟烫,我們自己想一下解決方案
-
加硬盤,簡(jiǎn)單粗暴
-
加電腦迄本,文件拆分存儲(chǔ)(分布式存儲(chǔ))
第一種方案硕淑,最簡(jiǎn)單,一個(gè)容量很大的超級(jí)電腦嘉赎,但有終歸是有上限置媳,硬盤不可能無限擴(kuò)容,成本也比較高公条,舍棄
與其對(duì)比拇囊,第二種方案就靠譜的多,我可以用很多廉價(jià)電腦共同承擔(dān)存儲(chǔ)工作靶橱,每個(gè)電腦存儲(chǔ)一部分寥袭,隨著數(shù)據(jù)量不斷增多,不斷的增加電腦就可以关霸,這就是一種分布式的存儲(chǔ)
但實(shí)現(xiàn)起來真的很困難传黄,需要做的事情有很多
- 把文件拆分成塊,存入不同的電腦
- 記錄每臺(tái)電腦的存儲(chǔ)位置队寇,以便取文件
- 取文件要每臺(tái)電腦取分塊
- 取回所有分塊后再合并恢復(fù)原文件
一次存取要同時(shí)操作多臺(tái)電腦膘掰,又要進(jìn)行拆分合并的操作
而HDFS的存在就是為了讓文件的存取者從這繁雜的工作中解脫出來:
HDFS整合了每臺(tái)電腦的資源,對(duì)外抽象出一個(gè)類似linux系統(tǒng)的目錄結(jié)構(gòu)佳遣,用戶使用HDFS只需要像操作單機(jī)一樣存取文件即可识埋,HDFS內(nèi)部完成文件的分塊凡伊、分布式存儲(chǔ)等功能,并且還額外提供了自動(dòng)備份功能防止丟失
并且HDFS還提供了類似linux的文件操作命令:mkdir
/rm
/cd
/ls
/cat
等窒舟,儼然成了一個(gè)和linux文件系統(tǒng)使用基本一致的分布式文件系統(tǒng)
- 傳統(tǒng)的文件系統(tǒng)(linux/windows)系忙,基于單機(jī)磁盤,抽象出文件夾辜纲,我們不用關(guān)心文件到底存在哪塊硬盤上
- 分布式文件系統(tǒng)(hdfs)笨觅,基于多個(gè)傳統(tǒng)文件系統(tǒng)集群,抽象出文件夾耕腾,我們不用關(guān)心文件到底存在哪個(gè)電腦上
原理
HDFS是如何實(shí)現(xiàn)做到的吶
DataNode
首先要在集群每臺(tái)機(jī)器上運(yùn)行一個(gè)節(jié)點(diǎn):DataNode
见剩,實(shí)際上就是一個(gè)運(yùn)行在服務(wù)器上的常駐java程序,這個(gè)DataNode
承擔(dān)的主要責(zé)任很簡(jiǎn)單
- 接收上傳的文件塊并落盤
- 確保數(shù)據(jù)完整性(未損壞)
- 根據(jù)下載指令獲取某文件塊
每臺(tái)機(jī)器都有一個(gè)DataNode可以承擔(dān)存取的任務(wù)扫俺,但有上傳任務(wù)時(shí)怎么選擇苍苞,取文件有去哪幾個(gè)取吶,真是三個(gè)和尚沒水喝
NameNode
因此這些分布在各個(gè)機(jī)器上的DataNode
需要有一個(gè)統(tǒng)一的協(xié)調(diào)者狼纬、管理者羹呵、門面擔(dān)當(dāng),就是NameNode
NameNode
同樣是一個(gè)運(yùn)行在服務(wù)器的常駐java進(jìn)程疗琉,它本身不具有存取功能冈欢,但他負(fù)責(zé)管理協(xié)調(diào)所有的DataNode
(就像產(chǎn)品經(jīng)理,可能自己不會(huì)寫代碼盈简,但手下員工都會(huì)寫凑耻,那么對(duì)于客戶來說,產(chǎn)品經(jīng)理就有寫代碼的能力)
一個(gè)NameNode
+多個(gè)DataNode
構(gòu)成了master/slave集群(主從架構(gòu))
NameNode
對(duì)外抽象出一個(gè)類似linux系統(tǒng)的文件夾柠贤,用戶存文件時(shí)香浩,只需告知存儲(chǔ)在哪個(gè)文件夾下,NameNode
內(nèi)部會(huì)協(xié)調(diào)具體存在哪個(gè)DataNode
節(jié)點(diǎn)上臼勉,取文件同理邻吭,只需告知取哪個(gè)文件夾下的哪個(gè)文件即可
同時(shí)NameNode
可以提數(shù)據(jù)供備份能力,可以根據(jù)用戶配置的備份數(shù)量自動(dòng)選擇備份的節(jié)點(diǎn)
Fsimage和Edits
NameNode
作為DataNode
管理者宴霸,程序內(nèi)部維護(hù)了一個(gè)目錄數(shù)據(jù)結(jié)構(gòu)囱晴,記錄了文件系統(tǒng)有哪些目錄,每個(gè)目錄有什么文件瓢谢,文件被分成多少塊畸写,每一塊具體存在哪個(gè)節(jié)點(diǎn)上
那么有個(gè)問題,這些數(shù)據(jù)存在哪里恩闻?
- 首先艺糜,為了快速響應(yīng)剧董,作為一個(gè)java程序幢尚,這些數(shù)據(jù)內(nèi)存中肯定要存一份的
- 其次破停,為了重啟后恢復(fù)數(shù)據(jù),這些數(shù)據(jù)又一定要持久化到磁盤
所以內(nèi)存和磁盤中都要有完整的最新數(shù)據(jù)尉剩,這就比較麻煩真慢,因?yàn)槲覀冎来疟PIO操作性能是很差的,如果每次有文件變動(dòng)理茎,都修改磁盤數(shù)據(jù)黑界,這會(huì)導(dǎo)致程序很慢
其實(shí)這種問題早就有解決方案,比如redis就常用用這種方式持久化:快照+日志
Fsimage
文件就是NameNode
在磁盤中保存的快照皂林,存儲(chǔ)了某一時(shí)刻的內(nèi)存完整數(shù)據(jù)朗鸠,但會(huì)有延遲,一般隔很長(zhǎng)時(shí)間才快照一次础倍,因?yàn)檫@個(gè)快照的磁盤IO操作很耗時(shí)
因?yàn)槭褂?code>Fsimage恢復(fù)數(shù)據(jù)肯定會(huì)損失很多新數(shù)據(jù),所以需要配合日志文件:Edits
,日志文件就是每來一條修改數(shù)據(jù)的命令(創(chuàng)建文件夾或上傳文件)就追加一條操作日志到Edits
文件焙压,雖然同樣是磁盤操作段审,但這屬于順序讀寫的磁盤操作,速度是很快的
重啟時(shí)德迹,只需某一時(shí)刻的快照Fsimage
+之后的Edits
文件就可以還原完整數(shù)據(jù)
同時(shí)生成新快照時(shí)也可以使用Fsimage
+Edits
生成新的快照文件芽卿,一般隔一小時(shí)生成一次
SecondaryNameNode
每隔一段時(shí)間/日志文件太大情況下,需要生成新的Fsimage快照文件胳搞,這個(gè)過程叫checkpoint
卸例,這個(gè)活本該又管理者NameNode來做,但畢竟這個(gè)工作量比較負(fù)責(zé)又涉及磁盤IO流酬,做這些事會(huì)耽誤NameNode的效率
既然領(lǐng)導(dǎo)有更重要的活要做币厕,這種繁瑣浪費(fèi)時(shí)間的活就交給秘書來做就可以,這個(gè)負(fù)責(zé)checkpoint
的秘書就是SecondaryNameNode
SecondaryNameNode
同樣是一個(gè)java程序芽腾,一般運(yùn)行在與NameNode不同的服務(wù)器上旦装,她負(fù)責(zé)詢問NameNode是否需要chekpoint
,得到肯定答復(fù)就開始執(zhí)行checkpoint
操作摊滔,最終生成新的快照文件傳給NameNode
HDFS客戶端
以上講述DataNode負(fù)責(zé)存儲(chǔ)阴绢,NameNode負(fù)責(zé)管理DataNode并對(duì)外提供一個(gè)文件夾目錄,在上傳時(shí)指定負(fù)責(zé)存儲(chǔ)的DataNode艰躺,并且記錄文件存儲(chǔ)的節(jié)點(diǎn)(實(shí)際上文件存儲(chǔ)節(jié)點(diǎn)并沒有存儲(chǔ)呻袭,而是動(dòng)態(tài)更新),在下載時(shí)告訴客戶去哪里取文件
那么作為用戶就需要完成其余的工作:
- 文件上傳前分塊
- 與NameNode溝通獲取要上傳/下載的DataNode節(jié)點(diǎn)信息
- 與指定的DataNode節(jié)點(diǎn)交互腺兴,完成上傳/下載
- 下載后合并恢復(fù)文件
還是很麻煩左电,于是HDFS又提供了一個(gè)客戶端,這些活它來干,客戶還是只是單純的上傳下載文件即可
客戶端本質(zhì)就是一個(gè)寫好的java代碼篓足,我們執(zhí)行這個(gè)代碼就可以很輕松的完成上傳/下載段誊,包括創(chuàng)建目錄
在hadoop服務(wù)器上,我們可以通過hadoop fs
命令或者hadoop dfs
命令執(zhí)行客戶端上傳/下載/目錄操作
在本地ide中栈拖,我們可以引入hadoop-client
(包含了分塊,與NameNode和DataNode交互的邏輯)依賴來用自己的代碼實(shí)現(xiàn)客戶端的上傳/下載/目錄操作
總結(jié)
最終HDFS示意圖如下
總結(jié)一下:
HDFS是一個(gè)分布式文件系統(tǒng)连舍,與我們用的windows/linux文件系統(tǒng)功能基本一致,只不過它的底層是把文件存儲(chǔ)在了分布式的計(jì)算機(jī)上
YARN
概念
yarn是hadoop的另一重要組件涩哟,hdfs是解決大數(shù)據(jù)的存儲(chǔ)問題索赏,yarn是解決大數(shù)據(jù)的計(jì)算問題的
大數(shù)據(jù)的存儲(chǔ)我們用多臺(tái)電腦解決了,大數(shù)據(jù)的計(jì)算一樣可以用這個(gè)思維:
一臺(tái)電腦算不過來贴彼,多來幾個(gè)電腦同時(shí)算就好了
且yarn完善了hadoop潜腻,如果只有hdfs,集群中的每臺(tái)電腦只貢獻(xiàn)了磁盤和支持NameNode器仗、DataNode運(yùn)行的少部分內(nèi)存和cpu砾赔,剩余很多內(nèi)存和cpu限制,我們知道程序的運(yùn)行最需要的資源就是內(nèi)存和CPU資源
YARN把這些分布在不同電腦的cpu和內(nèi)存組織調(diào)度起來青灼,統(tǒng)一對(duì)外部形成了一個(gè)龐大的可擴(kuò)展的超級(jí)電腦
有了yarn提供的龐大的cpu和內(nèi)存資源暴心,我們就可以把應(yīng)用程序作業(yè)的壓力分布在不同計(jì)算機(jī)上,就解決了大數(shù)據(jù)的計(jì)算難題
yarn就像是一個(gè)大的操作系統(tǒng)杂拨,我們可以編寫應(yīng)用程序在yarn上運(yùn)行专普,程序中我們可以向yarn再次申請(qǐng)資源并在其它電腦上執(zhí)行子程序,這就好比我們java程序新建一個(gè)線程去跑子任務(wù)弹沽,只不過yarn中新建的子任務(wù)可能運(yùn)行在其它電腦上
- 傳統(tǒng)的操作系統(tǒng)(linux/windows)檀夹,基于單機(jī)cpu和內(nèi)存,我們可以開發(fā)應(yīng)用程序策橘,程序中可以創(chuàng)建子線程炸渡,線程具體執(zhí)行在哪個(gè)cpu上我們不用關(guān)心,操作系統(tǒng)負(fù)責(zé)調(diào)度
- 分布式操作系統(tǒng)(yarn)丽已,基于多個(gè)傳統(tǒng)操作系統(tǒng)集群蚌堵,我們可以開發(fā)應(yīng)用程序,程序中可以創(chuàng)建子進(jìn)程沛婴,進(jìn)程具體執(zhí)行在哪個(gè)電腦上我們不用關(guān)心吼畏,yarn系統(tǒng)負(fù)責(zé)調(diào)度
Container
container的概念
container是yarn中的資源抽象,所有人都這么說嘁灯,但這句話本身就夠抽象了泻蚊。。丑婿。
可以這么理解性雄,container是一個(gè)進(jìn)程(程序)或其子進(jìn)程(子程序)運(yùn)行的資源限制没卸,運(yùn)行在某個(gè)container上的進(jìn)程只能使用container規(guī)定的資源,這里的資源主要指cpu和內(nèi)存
我們描述某個(gè)container可以這么描述
192.168.1.X這臺(tái)機(jī)器上的1G內(nèi)存和兩個(gè)cpu
那么運(yùn)行在這個(gè)container上的進(jìn)程上的應(yīng)用只能使用1G的內(nèi)存和兩個(gè)CPU(yarn內(nèi)部使用linux的cgroup進(jìn)行資源限制)
所以container是一個(gè)程序可使用的資源范圍秒旋,這個(gè)范圍在程序啟動(dòng)前就限制住了办悟,所以container確實(shí)是一個(gè)資源的抽象,也是一個(gè)進(jìn)程運(yùn)行的容器
container的大小
那么一個(gè)container具體是多大內(nèi)存多少cpu吶滩褥?
這主要取決于我們的應(yīng)用程序到底需要多少,比如某個(gè)應(yīng)用程序需要2G內(nèi)存和4個(gè)CPU炫加,那么可以向yarn申請(qǐng)瑰煎,yarn如果有足夠的剩余資源就可以給應(yīng)用分配,所分配的container就是某單臺(tái)機(jī)器上的2G內(nèi)存和4個(gè)CPU
當(dāng)然container的大小是有限制的俗孝,不可能隨意申請(qǐng)酒甸,但這個(gè)限制可以自己配置
container的作用
為什么yarn要用container限制進(jìn)程的資源使用吶?
主要是為了合理調(diào)度赋铝,比如一臺(tái)機(jī)器有8個(gè)CPU插勤、8G內(nèi)存,某個(gè)應(yīng)用程序申請(qǐng)了container占用了4個(gè)CPU和4G內(nèi)存革骨,這臺(tái)機(jī)器剩余就是4個(gè)CPU和4G內(nèi)存农尖,下次再有任務(wù)時(shí)就可以根據(jù)剩余資源考慮要不要在這臺(tái)機(jī)器上運(yùn)行
再就是這種資源隔離也避免了多應(yīng)用程序之間互相爭(zhēng)搶,這就是劉華強(qiáng)口中的先明后不爭(zhēng)
container總結(jié)
yarn使用container這個(gè)概念更加細(xì)粒度的管理集群中每臺(tái)機(jī)器的資源良哲,container作為容器使各程序之間資源隔離
原理
接下來講一下yarn是如何實(shí)現(xiàn)的多臺(tái)機(jī)器的統(tǒng)一調(diào)度盛卡,以及如何劃分管理container
NodeManage(NM)
和HDFS的DataNode類似,Yarn的集群每臺(tái)機(jī)器也跑了一個(gè)常駐jvm進(jìn)程:NodeManage
筑凫,它是單臺(tái)機(jī)器的資源管理者滑沧,承擔(dān)以下責(zé)任
- 記錄機(jī)器的所有資源
- 可以按命令運(yùn)行應(yīng)用程序,并按規(guī)定的container限制應(yīng)用程序的資源使用巍实,即在container容器中運(yùn)行程序
- 實(shí)時(shí)記錄拋去運(yùn)行container占用后的剩余資源
ResourceManager(RM)
與HDFS的NameNode類似滓技,是所有機(jī)器上的NodeManage的統(tǒng)一管理者和門面,主要承擔(dān)以下責(zé)任
- 管理NM棚潦,NM要與RM進(jìn)行心跳來回報(bào)自己的狀態(tài)令漂,剩余資源等信息
- 對(duì)外抽象出一個(gè)大的程序可用資源:所有機(jī)器的內(nèi)存/CPU之和
- 管理所有應(yīng)用程序,主要為了調(diào)度其運(yùn)行時(shí)機(jī)
- 按照應(yīng)用程序的要求選擇合適的NM丸边,以便后續(xù)運(yùn)行程序
-
通過調(diào)度調(diào)節(jié)多應(yīng)用程序的執(zhí)行順序洗显,執(zhí)行節(jié)點(diǎn)等
其中RM的調(diào)度器有很多種方式,是一種可插拔的調(diào)度器(可以自定義)原环,比較常用的有
- FIFo Scheduler(先進(jìn)先出調(diào)度器挠唆,Hadoop自帶的)
- Capacity scheduler(容量調(diào)度器,Yahoo寫的)
- Fair scheduler(公平調(diào)度器 FaceBook寫的)
調(diào)度器主要作用就是控制多程序誰(shuí)先執(zhí)行誰(shuí)后執(zhí)行嘱吗,穿插執(zhí)行等玄组,主要為了資源更好的被利用滔驾,提升程序運(yùn)行速度,就像windows操作系統(tǒng)也有自己的調(diào)度器俄讹,它會(huì)決定哪些線程先執(zhí)行哆致,哪些后執(zhí)行,如何執(zhí)行
應(yīng)用
上文說yarn相當(dāng)于一個(gè)操作系統(tǒng)患膛,我們可以編寫應(yīng)用程序在yarn上運(yùn)行
yarn上運(yùn)行的最經(jīng)典的應(yīng)用當(dāng)屬hadoop自帶的MapReduce
還有很多第三方開發(fā)的運(yùn)行在yarn上的程序摊阀,如大名鼎鼎的HBase、Spark等
當(dāng)然我們也可以自己寫一個(gè)應(yīng)用程序運(yùn)行在yarn上
當(dāng)然運(yùn)行在yarn上的程序就要遵守yarn的規(guī)矩
因?yàn)樵赮arn上運(yùn)行的程序一般都會(huì)有子程序(否則就是單機(jī)運(yùn)行了踪蹬,沒有必要在yarn上跑)胞此,所以Yarn中應(yīng)用的主程序成為ApplicationMaster
,簡(jiǎn)稱AM
跃捣,就相當(dāng)于Java單機(jī)開發(fā)中的主線程Main-Thread
AM
代碼中需要注冊(cè)到RM漱牵,也可以向RM申請(qǐng)額外的container來運(yùn)行子程序
有了HDFS的磁盤管理,加上YARN的CPU和內(nèi)存管理疚漆,HADOOP就成為了一個(gè)可擴(kuò)展的超級(jí)操作系統(tǒng)酣胀,大數(shù)據(jù)的存儲(chǔ)和計(jì)算也就不在話下了
MapReduce
上面也提到了,YARN相當(dāng)于操作系統(tǒng)娶聘,MapReduce是運(yùn)行在其上的一種應(yīng)用程序
準(zhǔn)確的說MapReduce更像spring這樣的一個(gè)程序框架闻镶,我們可以定制map和reduce方法,最終打包成應(yīng)用程序jar包運(yùn)行在yarn上
MapReduce特別適合大文本文件的內(nèi)容分析丸升,比如日志分析
MapReduce分為Map和Reduce儒溉,其中
- Map主要進(jìn)行每行的分析,把關(guān)鍵標(biāo)志信息作為key发钝,value存儲(chǔ)相關(guān)要計(jì)算的信息顿涣,生成一個(gè)Map結(jié)構(gòu)
- Reduce翻譯過來是“減少”,減少的方式就是針對(duì)map相同key的合并酝豪,類似于sql中的group by涛碑,通過合并加計(jì)算可以得到最終的結(jié)果
那hadoop官方WordCount程序舉例,該方法主要統(tǒng)計(jì)每個(gè)單次出現(xiàn)的次數(shù)
最終計(jì)算出java出現(xiàn)2次孵淘,hadoop出現(xiàn)2次蒲障。。瘫证。
由于計(jì)算文件一般超大揉阎,一臺(tái)電腦計(jì)算太慢,MapReduce會(huì)把文件切片背捌,MapReduce的AM程序會(huì)申請(qǐng)多個(gè)container執(zhí)行Map任務(wù)毙籽,所有Map結(jié)束后又會(huì)申請(qǐng)多個(gè)container執(zhí)行Reduce任務(wù),這樣就把超大文件的計(jì)算壓力分布在各個(gè)機(jī)器上
最后
最后在再次總結(jié)一下:
hadoop的hdfs+yarn組成了一個(gè)可擴(kuò)展的的超級(jí)操作系統(tǒng)毡庆,在這個(gè)操作系統(tǒng)上我們可以存儲(chǔ)超大數(shù)據(jù)坑赡,也可以通過執(zhí)行MapReduce這樣的應(yīng)用程序來完成大數(shù)據(jù)的處理
之后我會(huì)介紹如何在Yarn上運(yùn)行一個(gè)自己寫的分布式小程序