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