Hadoop分布式文件系統(tǒng)--HDFS的誕生
1.牛刀小試
張大胖找了個(gè)實(shí)習(xí)的工作, ***天上班Bill師傅給他分了個(gè)活兒:日志分析。
張大胖拿到了師傅給的日志文件,大概有幾十兆,打開一看, 每一行都長(zhǎng)得差不多,類似這樣:
212.86.142.33 – - [20/Mar/2017:10:21:41 +0800] “GET / HTTP/1.1″ 200 986 “http://www.baidu.com/” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; )"
張大胖知道,這些日志都是Web服務(wù)器產(chǎn)生的,里邊包含了像客戶端IP, 訪問時(shí)間, 請(qǐng)求的URL,請(qǐng)求處理的狀態(tài), referer, User Agent等信息。
師傅說,你想個(gè)辦法統(tǒng)計(jì)一天之內(nèi)每個(gè)頁面的訪問量(PV),獨(dú)立的IP數(shù), 還有用戶最喜歡搜索的前10個(gè)關(guān)鍵字。
張大胖心說這簡(jiǎn)單啊,我用Linux上的cat,awk等小工具就能做出來, 不過還是正式一點(diǎn),用我最喜歡的Python寫個(gè)程序吧,把每一行文本分割成一個(gè)個(gè)字段,然后分分組、計(jì)算一下不就得了。
慢著, 這樣一來這個(gè)程序就只能干這些事兒,不太靈活,擴(kuò)展性不太好。
要不把分割好的字段寫入數(shù)據(jù)庫(kù)表?
比如access_log(id,ip,timestamp,url, status,referer, user_agent), 這樣就能利用數(shù)據(jù)庫(kù)的group 功能和count功能了,sql多強(qiáng)大啊, 想怎么處理就怎么處理。
對(duì),就這么辦!
半天以后,張大胖就把這個(gè)程序給搞定了,還畫了一個(gè)架構(gòu)圖,展示給了師傅。
師傅一看:“不錯(cuò)嘛,思路很清晰,還考慮到了擴(kuò)展性,可以應(yīng)對(duì)以后更多的需求。”
于是這個(gè)小工具就這么用了起來。
張大胖畢業(yè)以后也順利地加入了這家公司。
2.分布式
互聯(lián)網(wǎng)尤其是移動(dòng)互聯(lián)網(wǎng)發(fā)展得極快,公司網(wǎng)站的用戶量暴增,訪問量也水漲船高,日志量也很感人,每小時(shí)都能產(chǎn)生好幾個(gè)G,張大胖實(shí)習(xí)期間“引以為傲”的小程序沒法再用了,數(shù)據(jù)庫(kù)根本就放不下啊。
不僅數(shù)據(jù)庫(kù)放不下,在Web服務(wù)器上也放不下了,更不用說去做分析了。
張大胖主動(dòng)請(qǐng)纓,打算搞定這個(gè)問題。 當(dāng)然他也很聰明地把經(jīng)驗(yàn)豐富的師傅Bill給拉上了。
兩個(gè)人來到會(huì)議室,開始了討論。
張大胖先算了一筆賬:如果是一臺(tái)機(jī)器,一個(gè)硬盤,讀取速度是75M/s ,那需要花費(fèi)10多天才能讀取100T的內(nèi)容。 但是如果是有100個(gè)硬盤, 并行的讀取速度就能達(dá)到75G/s , 幾十分鐘就可以把100T的數(shù)據(jù)給讀出來了,多快啊。
他對(duì)Bill說道:“看來只有分布式存儲(chǔ)才能拯救了。多來幾臺(tái)機(jī)器吧,把log1, log2,log3...這些文件存放在不同的機(jī)器上。”
師傅Bill說道:“你想得太簡(jiǎn)單了,分布式可不是簡(jiǎn)單地添加機(jī)器, 機(jī)器的硬盤壞了怎么辦?日志文件是不是就丟失了? 熱門文件怎么辦? 訪問量特別大,那對(duì)應(yīng)的機(jī)器負(fù)載就特別高, 這樣不公平啊!
張大胖說道:“***個(gè)問題好辦,我可以做備份啊,把每個(gè)文件都存三個(gè)備份。這樣壞的可能性就大大降低了。你說的第二個(gè)問題,我們的日志哪有什么熱門文件?”
“要考慮下通用性嘛!將來你這個(gè)分布式的文件系統(tǒng)可以處理別的東西啊。”
“好吧, 我可以被文件切成小塊,讓他們分散在各個(gè)機(jī)器上,這就行了吧。 備份的時(shí)候,把每個(gè)小塊都備份三份就解決問題了。”
(備注:三份是***要求)
“那問題就來了,我們?cè)撛趺词褂媚兀?客戶端總不能說把文件的***塊從服務(wù)器1上取出來,第二塊從服務(wù)器4上取出來,第三塊從服務(wù)器2上取出來..... 再說客戶端保留這些‘亂七八糟’的信息該多煩人啊。” Bill提出的問題很致命。
“這個(gè)......” 張大胖思考了半天, “看來還得做抽象啊,我的分布式文件系統(tǒng)得提供一個(gè)抽象層,讓文件分塊對(duì)客戶端保持透明, 客戶端根本不必知道文件是怎么分塊的,分塊后存放在什么服務(wù)器上。他們只需要知道一個(gè)文件的路徑/logs/log1,就可以讀寫了,細(xì)節(jié)不用操心。”
“不錯(cuò),看來你已經(jīng)Get到了,一定要通過抽象給客戶端提供一個(gè)簡(jiǎn)單的視圖,盡可能讓他們像訪問本地文件一樣來使用!” Bill 立刻做了升華。
“不過,”張大胖突然想到一個(gè)問題,“這樣的分布式文件系統(tǒng)似乎只適合在文件末尾不斷地對(duì)追加內(nèi)容,如果是想隨機(jī)地讀寫,比如定位到某個(gè)位置,然后寫入新的數(shù)據(jù),就很麻煩了。”
“這也沒辦法,事物總是有利有弊,現(xiàn)在的系統(tǒng)就是適合一次寫入,多次讀取的場(chǎng)景。”
3.元數(shù)據(jù)
“不過, ”Bill 接著說,“文件被分成了哪些塊,這些塊都放在什么服務(wù)器上,系統(tǒng)有哪些服務(wù)器,服務(wù)器上都多大空間,這些都是Metadata, 你得專門找個(gè)服務(wù)器存儲(chǔ)起來,我們把這個(gè)服務(wù)器叫做Metadata節(jié)點(diǎn)如何?或者簡(jiǎn)單一點(diǎn),叫做NameNode吧!類似于整個(gè)系統(tǒng)的大管家。 ”
“好, 我們把那些儲(chǔ)存數(shù)據(jù)的服務(wù)器叫做Data節(jié)點(diǎn)(DataNode)吧,這樣就區(qū)分開了。我可以寫一個(gè)客戶端讓大家使用,這個(gè)客戶端通過查詢NameNode,定位到文件的分塊和存儲(chǔ)位置,這樣大家就可以讀寫了!”
Bill在白板上畫了一張圖,展示了當(dāng)前的設(shè)計(jì):
“綠色虛線的意思是數(shù)據(jù)的讀寫流, 對(duì)吧, 但是橙色的虛線是什么鬼?” 張大胖問道。
“你想想這么一種情況,如果某個(gè)Datanode 的機(jī)器掛掉了,它上面的所有文件分塊都無法讀寫了,這時(shí)候Namenode如何才能知道呢? 還有,如果某個(gè)Datanode所在機(jī)器的磁盤空間不足了,是不是也得讓Namenode這個(gè)大管家知道?”
“奧,Datanode和Namenode 之間需要定期的通信, 這就麻煩了,我還得特別為他們?cè)O(shè)計(jì)一個(gè)通信協(xié)議??!” 張大胖有點(diǎn)沮喪。
“分布式系統(tǒng)就是這樣,有很多挑戰(zhàn),機(jī)器壞掉,網(wǎng)絡(luò)斷掉..... 你想在普通的、廉價(jià)的機(jī)器上實(shí)現(xiàn)高可靠性是很難的一件事情。”
4.讀取文件
“我們?cè)偌?xì)化下讀寫的流程吧?” Bill 提議。
“我覺得挺簡(jiǎn)單啊,比如去讀取一個(gè)文件,客戶端只需把文件名告訴Namenode, 讓Namenode把所有數(shù)據(jù)都返回不就行了?這樣客戶端對(duì)Datanode保持透明,不錯(cuò)吧!”
Bill嚴(yán)肅地?fù)u了搖頭:“不行, 如果所有的數(shù)據(jù)流都經(jīng)過Namenode, 它會(huì)成為瓶頸的! 無法支持多個(gè)客戶端的并發(fā)訪問, 記住,我們要處理的可是TB, 乃至PB級(jí)別的數(shù)據(jù)啊。”
“對(duì)對(duì),我沒有深入考慮??!” 張大胖感慨姜還是老的辣,趕緊換個(gè)思路, “要不這樣,讀取文件的時(shí)候,Namenode只返回文件的分塊以及該分塊所在的Datanode列表, 這樣我們的客戶端就可以選擇一個(gè)Datanode來讀取文件了。”
“但是一個(gè)分塊有3個(gè)備份,到底選哪個(gè)? ” Bill問道
“肯定是最近的那個(gè)了,嗯,怎么定義遠(yuǎn)近呢?” 張大胖犯難了。
“我們可以定義一個(gè)‘距離’的概念。 ” Bill 說道。
客戶端和Datanode是同一個(gè)機(jī)器 : 距離為0 ,表示最近
客戶端和Datanode是同一個(gè)機(jī)架的不同機(jī)器 : 距離為2 ,稍微遠(yuǎn)一點(diǎn)
客戶端和Datanode位于同一個(gè)數(shù)據(jù)中心的不同機(jī)架上 : 距離為4, 更遠(yuǎn)一點(diǎn)
“沒想到分布式系統(tǒng)這么難搞,比我實(shí)習(xí)做的那個(gè)程序難度提高了好幾個(gè)數(shù)量級(jí)!”
話雖這么說,張大胖還是畫了一個(gè)讀取文件的流程圖:
(注:圖中只畫出了一個(gè)分塊的讀取,對(duì)文件其他分塊的讀取還會(huì)持續(xù)進(jìn)行)
5.寫入文件
“寫入文件也類似,” 張大胖打算趁熱打鐵,“讓Namenode 找到可以寫數(shù)據(jù)的三個(gè)Datanode,返回給我們的客戶端,客戶端就可以向這三個(gè)Datanode 發(fā)起寫的操作了!”
“假設(shè)你有個(gè)10G的文件,難道讓客戶端向Datanode寫入3次,使用30G的流量嗎?” Bill馬上提了一個(gè)關(guān)鍵的問題。
“不這么做還能怎么辦? 我們要保存多個(gè)備份?。?rdquo;
“有個(gè)解決辦法,我們可以把三個(gè)Datanode 組成一個(gè)Pipline(管道), 我們只把數(shù)據(jù)發(fā)給***個(gè)Datanode, 讓數(shù)據(jù)在這個(gè)管道內(nèi)‘流動(dòng)’起來, ***個(gè)Datanode發(fā)個(gè)備份給第二個(gè), 第二個(gè)發(fā)同樣的備份給第三個(gè)。”
(注:實(shí)際的文件寫入比較復(fù)雜,有更多細(xì)節(jié), 這里只是重點(diǎn)展示pipeline)
“有點(diǎn)意思,客戶端只發(fā)出一次寫的請(qǐng)求,數(shù)據(jù)的復(fù)制由我們的Datanode合作搞定。” 張大胖深為佩服,師傅Bill的腦子就是好使啊。
“還有啊,”Bill說道,“咱們的設(shè)計(jì)中Namenode這個(gè)大管家有單點(diǎn)失敗的風(fēng)險(xiǎn),我們***還是做一個(gè)備份的節(jié)點(diǎn)。”
張大胖深表贊同。
6.結(jié)束?開始?
“我們給這個(gè)系統(tǒng)起個(gè)名字吧?叫Distrubted File System(簡(jiǎn)稱DFS)怎么樣?” 張大胖說。
“俗,太俗,叫Hadoop吧,這是我兒子玩具象的名稱。嗯,還是叫Hadoop Distributed File System, HDFS。” Bill 的提議出乎張大胖意料。
“行吧,我們有了HDFS,可以存儲(chǔ)海量的日志了,我就可以寫個(gè)程序,去讀取這些文件,統(tǒng)計(jì)各種各樣的用戶訪問了。”
“你打算把你的程序放到哪里?”
“自然是放在HDFS之外的某個(gè)機(jī)器上,然后通過HDFS 客戶端去訪問數(shù)據(jù)啊!”
“100T的數(shù)據(jù)從HDFS的眾多機(jī)器中讀取出來,在一臺(tái)機(jī)器上處理? 這得多慢??! 我們要考慮把計(jì)算也做成分布式的,并且讓計(jì)算程序盡可能地靠近數(shù)據(jù),這樣就快了!”
“分布式計(jì)算?”
“沒錯(cuò),聽說過Mapreduce 沒有?”
張大胖搖了搖頭:“這是什么鬼?”
“我們下次再聊吧!”
后記:這篇文章介紹了HDFS的一些關(guān)鍵設(shè)計(jì)理念,已經(jīng)屬于非常簡(jiǎn)化的情況了,沒有考慮數(shù)據(jù)的完整性,節(jié)點(diǎn)失效等更多細(xì)節(jié)。
【本文為51CTO專欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過作者微信公眾號(hào)coderising獲取授權(quán)】