日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

分布式基礎(chǔ)學(xué)習(xí)【一】 —— 分布式文件系統(tǒng)

 gerial 2011-11-23

分布式基礎(chǔ)學(xué)習(xí)【一】 —— 分布式文件系統(tǒng)

分布式基礎(chǔ)學(xué)習(xí)

所謂分布式,在這里,很狹義的指代以Google的三駕馬車,GFS、Map/ReduceBigTable為 框架核心的分布式存儲(chǔ)和計(jì)算系統(tǒng)。通常如我一樣初學(xué)的人,會(huì)以Google這幾份經(jīng)典的論文作為開端的。它們勾勒出了分布式存儲(chǔ)和計(jì)算的一個(gè)基本藍(lán)圖,已 可窺見其幾分風(fēng)韻,但終究還是由于缺少一些實(shí)現(xiàn)的代碼和示例,色彩有些斑駁,缺少了點(diǎn)感性。幸好我們還有Open Source,還有Hadoop。Hadoop是 一個(gè)基于Java實(shí)現(xiàn)的,開源的,分布式存儲(chǔ)和計(jì)算的項(xiàng)目。作為這個(gè)領(lǐng)域最富盛名的開源項(xiàng)目之一,它的使用者也是大牌如云,包括了 Yahoo,Amazon,F(xiàn)acebook等等(好吧,還可能有校內(nèi),不過這真的沒啥分量...)。Hadoop本身,實(shí)現(xiàn)的是分布式的文件系統(tǒng) HDFS,和分布式的計(jì)算(Map/Reduce)框架,此外,它還不是一個(gè)人在戰(zhàn)斗,Hadoop包含一系列擴(kuò)展項(xiàng)目,包括了分布式文件數(shù)據(jù)庫HBase(對(duì)應(yīng)Google的BigTable),分布式協(xié)同服務(wù)ZooKeeper(對(duì)應(yīng)Google的Chubby),等等。。。
如此,一個(gè)看上去不錯(cuò)的黃金搭檔浮出水面,Google的論文 + Hadoop的實(shí)現(xiàn),順著論文的框架看具體的實(shí)現(xiàn),用實(shí)現(xiàn)來進(jìn)一步理解論文的邏輯,看上去至少很美。網(wǎng)上有很多前輩們,做過Hadoop相關(guān)的源碼剖析工作,我關(guān)注最多的是這里,目前博主已經(jīng)完成了HDFS的剖析工作,Map/Reduce的剖析正火熱進(jìn)行中,更新頻率之高,剖析之詳盡,都是難得一見的,所以,走過路過一定不要錯(cuò)過了。此外,還有很多Hadoop的關(guān)注者和使用者貼過相關(guān)的文章,比如:這里,這里。也可以去Hadoop的中文站點(diǎn)(不知是民間還是官方...),搜羅一些學(xué)習(xí)資料。。。
我個(gè)人從上述資料中受益匪淺,而我自己要做的 整理,與原始的源碼剖析有些不同,不是依照實(shí)現(xiàn)的模塊,而是基于論文的脈絡(luò)和實(shí)現(xiàn)這樣系統(tǒng)的基本脈絡(luò)來進(jìn)行的,也算,從另一個(gè)角度給出一些東西吧。鑒于個(gè) 人對(duì)于分布式系統(tǒng)的理解非常的淺薄,缺少足夠的實(shí)踐經(jīng)驗(yàn),深入的問題就不班門弄斧了,僅做梳理和解析,大牛至此,可繞路而行了。。。

一. 分布式文件系統(tǒng)

分布式文件系統(tǒng),在整個(gè)分布式系統(tǒng)體系中處于最低層最基礎(chǔ)的地位,存儲(chǔ)嘛,沒了數(shù)據(jù),再好的計(jì)算平臺(tái),再完善的數(shù)據(jù)庫系統(tǒng),都成了無水之舟了。那么,什么是分布式文件系統(tǒng),顧名思義,就是分布式+文件系統(tǒng)。 它包含這兩個(gè)方面的內(nèi)涵,從文件系統(tǒng)的客戶使用的角度來看,它就是一個(gè)標(biāo)準(zhǔn)的文件系統(tǒng),提供了一系列API,由此進(jìn)行文件或目錄的創(chuàng)建、移動(dòng)、刪除,以及 對(duì)文件的讀寫等操作。從內(nèi)部實(shí)現(xiàn)來看,分布式的系統(tǒng)則不再和普通文件系統(tǒng)一樣負(fù)責(zé)管理本地磁盤,它的文件內(nèi)容和目錄結(jié)構(gòu)都不是存儲(chǔ)在本地磁盤上,而是通過 網(wǎng)絡(luò)傳輸?shù)竭h(yuǎn)端系統(tǒng)上。并且,同一個(gè)文件存儲(chǔ)不只是在一臺(tái)機(jī)器上,而是在一簇機(jī)器上分布式存儲(chǔ),協(xié)同提供服務(wù),正所謂分布式。。。
因此,考量一個(gè)分布式文件系統(tǒng)的實(shí)現(xiàn),其實(shí)不 妨可以從這兩方面來分別剖析,而后合二為一。首先,看它如何去實(shí)現(xiàn)文件系統(tǒng)所需的基本增刪改查的功能。然后,看它如何考慮分布式系統(tǒng)的特點(diǎn),提供更好的容 錯(cuò)性,負(fù)載平衡,等等之類的。這二者合二為一,就明白了一個(gè)分布式文件系統(tǒng),整體的實(shí)現(xiàn)模式。。。

I. 術(shù)語對(duì)照

說任何東西,都需要統(tǒng)一一下語言先,不然明明 說的一個(gè)意思,卻容易被理解到另一個(gè)地方去。Hadoop的分布式文件系統(tǒng)HDFS,基本是按照Google論文中的GFS的架構(gòu)來實(shí)現(xiàn)的。但 是,HDFS為了彰顯其不走尋常路的本性,其中的大量術(shù)語,都與GFS截然不同。明明都是一個(gè)枝上長(zhǎng)的土豆,它偏偏就要叫山藥蛋,弄得水火不容的,苦了我 們看客。秉承老好人,誰也不得罪的方針,文中,既不采用GFS的叫法,也不采用Hadoop的稱謂,而是另辟蹊徑,自立門戶,搞一套自己的中文翻譯,為了 避免不必要的痛楚,特此先來一帖術(shù)語對(duì)照表,要不懂查一查,包治百病。。。

文中所用翻譯 HDFS中的術(shù)語 GFS中的術(shù)語 術(shù)語解釋
主控服務(wù)器 NameNode Master 整個(gè)文件系統(tǒng)的大腦,它提供整個(gè)文件系統(tǒng)的目錄信息,并且管理各個(gè)數(shù)據(jù)服務(wù)器。
數(shù)據(jù)服務(wù)器 DataNode Chunk Server 分布式文件系統(tǒng)中的每一個(gè)文件,都被切分成若干個(gè)數(shù)據(jù)塊,每一個(gè)數(shù)據(jù)塊都被存儲(chǔ)在不同的服務(wù)器上,此服務(wù)器稱之為數(shù)據(jù)服務(wù)器。
數(shù)據(jù)塊 Block Chunk 每個(gè)文件都會(huì)被切分成若干個(gè)塊,每一塊都有連續(xù)的一段文件內(nèi)容,是存儲(chǔ)的基恩單位,在這里統(tǒng)一稱做數(shù)據(jù)塊。
數(shù)據(jù)包 Packet 客戶端寫文件的時(shí)候,不是一個(gè)字節(jié)一個(gè)字節(jié)寫入文件系統(tǒng)的,而是累計(jì)到一定數(shù)量后,往文件系統(tǒng)中寫入一次,每發(fā)送一次的數(shù)據(jù),都稱為一個(gè)數(shù)據(jù)包。
傳輸塊 Chunk 在每一個(gè)數(shù)據(jù)包中,都會(huì)將數(shù)據(jù)切成更小的塊,每一個(gè)塊配上一個(gè)奇偶校驗(yàn)碼,這樣的塊,就是傳輸塊。
備份主控服務(wù)器 SecondaryNameNode 備用的主控服務(wù)器,在身后默默的拉取著主控服務(wù)器 的日志,等待主控服務(wù)器犧牲后被扶正。

*注:本文采用的Hadoop是0.19.0版本。

II. 基本架構(gòu)

1. 服務(wù)器介紹

與單機(jī)的文件系統(tǒng)不同,分布式文件系統(tǒng)不是將這些數(shù)據(jù)放在一塊磁盤上,由上層操作系統(tǒng)來管理。而是存放在一個(gè)服務(wù)器集群上,由集群中的服務(wù)器,各盡其責(zé),通力合作,提供整個(gè)文件系統(tǒng)的服務(wù)。其中重要的服務(wù)器包括:主控服務(wù)器(Master/NameNode),數(shù)據(jù)服務(wù)器(ChunkServer/DataNode),和客戶服務(wù)器。HDFS和GFS都是按照這個(gè)架構(gòu)模式搭建的。個(gè)人覺得,其中設(shè)計(jì)的最核心內(nèi)容是:文件的目錄結(jié)構(gòu)獨(dú)立存儲(chǔ)在一個(gè)主控服務(wù)器上,而具體文件數(shù)據(jù),拆分成若干塊,冗余的存放在不同的數(shù)據(jù)服務(wù)器上。
存儲(chǔ)目錄結(jié)構(gòu)的主控服務(wù)器,在GFS中稱為Master,在HDFS中稱為NameNode。 這兩個(gè)名字,叫得都有各自的理由,是瞎子摸象各表一面。Master是之于數(shù)據(jù)服務(wù)器來叫的,它做為數(shù)據(jù)服務(wù)器的領(lǐng)導(dǎo)同志存在,管理各個(gè)數(shù)據(jù)服務(wù)器,收集 它們的信息,了解所有數(shù)據(jù)服務(wù)器的生存現(xiàn)狀,然后給它們分配任務(wù),指揮它們齊心協(xié)力為系統(tǒng)服務(wù);而NameNode是針對(duì)客戶端來叫的,對(duì)于客戶端而言, 主控服務(wù)器上放著所有的文件目錄信息,要找一個(gè)文件,必須問問它,由此而的此名。。。
主控服務(wù)器在整個(gè)集群中,同時(shí)提供服務(wù)的只存在一個(gè),如果它不幸犧牲的話,會(huì)有后備軍立刻前赴后繼的跟上,但,同一時(shí)刻,需要保持一山不容二虎的態(tài)勢(shì)。這種設(shè)計(jì)策略,避免了多臺(tái)服務(wù)器間即時(shí)同步數(shù)據(jù)的代價(jià),而同時(shí),它也使得主控服務(wù)器很可能成為整個(gè)架構(gòu)的瓶頸所在。因此,盡量為主控服務(wù)器減負(fù),不然它做太多的事情,就自然而然的晉升成了一個(gè)分布式文件系統(tǒng)的設(shè)計(jì)要求。。。
每一個(gè)文件的具體數(shù)據(jù),被切分成若干個(gè)數(shù)據(jù)塊,冗余的存放在數(shù)據(jù)服務(wù)器。通常的配置,每一個(gè)數(shù)據(jù)塊的大小為64M, 在三個(gè)數(shù)據(jù)服務(wù)器上冗余存放(這個(gè)64M,不是隨便得來的,而是經(jīng)過反復(fù)實(shí)踐得到的。因?yàn)槿绻?,容易造成熱點(diǎn)的堆疊,大量的操作集中在一臺(tái)數(shù)據(jù)服務(wù)器 上,而如果太小的話,附加的控制信息傳輸成本,又太高了。因此沒有比較特定的業(yè)務(wù)需求,可以考慮維持此配置...)。數(shù)據(jù)服務(wù)器是典型的四肢發(fā)達(dá)頭腦簡(jiǎn)單 的苦力,其主要的工作模式就是定期向主控服務(wù)器匯報(bào)其狀況,然后等待并處理命令,更快更安全的存放好數(shù)據(jù)。。。
此外,整個(gè)分布式文件系統(tǒng)還有一個(gè)重要角色是客戶端。它不和主控服務(wù)和數(shù)據(jù)服務(wù)一樣,在一個(gè)獨(dú)立的進(jìn)程中提供服務(wù),它只是以一個(gè)類庫(包)的模式存在,為用戶提供了文件讀寫、目錄操作等APIs。當(dāng)用戶需要使用分布式文件系統(tǒng)進(jìn)行文件讀寫的時(shí)候,把客戶端相關(guān)包給配置上,就可以通過它來享受分布式文件系統(tǒng)提供的服務(wù)了。。。

2. 數(shù)據(jù)分布

一個(gè)文件系統(tǒng)中,最重要的數(shù)據(jù),其實(shí)就是整個(gè) 文件系統(tǒng)的目錄結(jié)構(gòu)和具體每個(gè)文件的數(shù)據(jù)。具體的文件數(shù)據(jù)被切分成數(shù)據(jù)塊,存放在數(shù)據(jù)服務(wù)器上。每一個(gè)文件數(shù)據(jù)塊,在數(shù)據(jù)服務(wù)器上都表征為出雙入隊(duì)的一對(duì) 文件(這是普通的Linux文件),一個(gè)是數(shù)據(jù)文件,一個(gè)是附加信息的元文件,在這里,不妨把這對(duì)文件簡(jiǎn)稱為數(shù)據(jù)塊文件。數(shù)據(jù)塊文件存放在數(shù)據(jù)目錄下,它有一個(gè)名為current的根目錄,然后里面有若干個(gè)數(shù)據(jù)塊文件和從dir0-dir63的最多64個(gè)的子目錄,子目錄內(nèi)部結(jié)構(gòu)等同于current目錄,依次類推(更詳細(xì)的描述,參見這里)。個(gè)人覺得,這樣的架構(gòu),有利于控制同一目錄下文件的數(shù)量,加快檢索速度。。。
這是磁盤上的物理結(jié)構(gòu),與之對(duì)應(yīng)的,是內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),用以表征這樣的磁盤結(jié)構(gòu),方便讀寫操作的進(jìn)行。Block類用于表示數(shù)據(jù)塊,而FSDataset類是數(shù)據(jù)服務(wù)器管理文件塊的數(shù)據(jù)結(jié)構(gòu),其中,FSDataset.FSDir對(duì)應(yīng)著數(shù)據(jù)塊文件和目錄,FSDataset.FSVolume對(duì)應(yīng)著一個(gè)數(shù)據(jù)目錄,FSDataset.FSVolumeSet是FSVolume的集合,每一個(gè)FSDataset有一個(gè)FSVolumeSet。多個(gè)數(shù)據(jù)目錄,可以放在不同的磁盤上,這樣有利于加快磁盤操作的速度。相關(guān)的類圖,可以參看這里 。。。
此外,與FSVolume對(duì)應(yīng)的,還有一個(gè)數(shù)據(jù)結(jié)構(gòu),就是DataStorage,它是Storage的子類,提供了升級(jí)、回滾等支持。但與FSVolume不一樣,它不需要了解數(shù)據(jù)塊文件的具體內(nèi)容,它只知道有這么一堆文件放這里,會(huì)有不同版本的升級(jí)需求,它會(huì)處理怎么把它們升級(jí)回滾之類的業(yè)務(wù)(關(guān)于Storage,可以參見這里)。而FSVolume提供的接口,都基本上是和Block相關(guān)的。。。
相比數(shù)據(jù)服務(wù)器,主控服務(wù)器的數(shù)據(jù)量不大,但邏輯更為復(fù)雜。主控服務(wù)器主要有三類數(shù)據(jù):文件系統(tǒng)的目錄結(jié)構(gòu)數(shù)據(jù)各個(gè)文件的分塊信息,數(shù)據(jù)塊的位置信息(就數(shù)據(jù)塊放置在哪些數(shù)據(jù)服務(wù)器上...)。在GFS和HDFS的架構(gòu)中,只有文件的目錄結(jié)構(gòu)和分塊信息才會(huì)被持久化到本地磁盤上,而數(shù)據(jù)塊的位置信息則是通過動(dòng)態(tài)匯總過來的,僅僅存活在內(nèi)存數(shù)據(jù)結(jié)構(gòu)中, 機(jī)器掛了,就灰飛煙滅了。每一個(gè)數(shù)據(jù)服務(wù)器啟動(dòng)后,都會(huì)向主控服務(wù)器發(fā)送注冊(cè)消息,將其上數(shù)據(jù)塊的狀況都告知于主控服務(wù)器。俗話說,簡(jiǎn)單就是美,根據(jù) DRY原則,保存的冗余信息越少,出現(xiàn)不一致的可能性越低,付出一點(diǎn)點(diǎn)時(shí)間的代價(jià),換取了一大把邏輯上的簡(jiǎn)單性,絕對(duì)應(yīng)該是一個(gè)包賺不賠的買賣。。。
在HDFS中,FSNamespacesystem類就負(fù)責(zé)保管文件系統(tǒng)的目錄結(jié)構(gòu)以及每個(gè)文件的分塊狀況的,其中,前者是由FSDirectory類來負(fù)責(zé),后者是各個(gè)INodeFile本身維護(hù)。在INodeFile里面,有一個(gè)BlockInfo的數(shù)組,保存著與該文件相關(guān)的所有數(shù)據(jù)塊信息,BlockInfo中包含了從數(shù)據(jù)塊到數(shù)據(jù)服務(wù)器的映射,INodeFile只需要知道一個(gè)偏移量,就可以提供相關(guān)的數(shù)據(jù)塊,和數(shù)據(jù)塊存放的數(shù)據(jù)服務(wù)器信息。。。

3、服務(wù)器間協(xié)議

在Hadoop的實(shí)現(xiàn)中,部署了一套R(shí)PC機(jī)制,以此來實(shí)現(xiàn)各服務(wù)間的通信協(xié)議。在Hadoop中,每一對(duì)服務(wù)器間的通信協(xié)議,都定義成為一個(gè)接口。服務(wù)端的類實(shí)現(xiàn)該接口,并且建立RPC服務(wù),監(jiān)聽相關(guān)的接口,在獨(dú)立的線程處理RPC請(qǐng)求。客戶端則可以實(shí)例化一個(gè)該接口的代理對(duì)象,調(diào)用該接口的相應(yīng)方法,執(zhí)行一次同步的通信,傳入相應(yīng)參數(shù),接收相應(yīng)的返回值?;诖薘PC的通信模式,是一個(gè)消息拉取的流程,RPC服務(wù)器等待RPC客戶端的調(diào)用,而不會(huì)先發(fā)制人主動(dòng)把相關(guān)信息推送到RPC客戶端去。。。
其實(shí)RPC的模式和原理,實(shí)在是沒啥好說的, 之所以說,是因?yàn)榭梢酝ㄟ^把握好這個(gè),徹底理順Hadoop各服務(wù)器間的通信模式。Hadoop會(huì)定義一些列的RPC接口,只需要看誰實(shí)現(xiàn),誰調(diào)用,就可 以知道誰和誰通信,都做些啥事情,圖中服務(wù)器的基本架構(gòu)、各服務(wù)所使用的協(xié)議、調(diào)用方向、以及協(xié)議中的基本內(nèi)容。。。

III. 基本的文件操作

基本的文件操作,可以分成兩類,一個(gè)是對(duì)文件 目錄結(jié)構(gòu)的操作,比如文件和目錄的創(chuàng)建、刪除、移動(dòng)、更名等等;另一個(gè)是對(duì)文件數(shù)據(jù)流的操作,包括讀取和寫入文件數(shù)據(jù)。當(dāng)然,文件讀和寫,是有本質(zhì)區(qū)別 的,尤其是在數(shù)據(jù)冗余的情況下,因此,當(dāng)成兩類操作也不足為過。此外,要具體到讀寫的類別,也是可以再繼續(xù)分類下去的。在GFS的論文中,對(duì)于分布式文件 系統(tǒng)的讀寫場(chǎng)景有一個(gè)重要的假定(其實(shí)是從實(shí)際業(yè)務(wù)角度得來的...):就是文件的讀取是由大數(shù)據(jù)量的連續(xù)讀取和小數(shù)據(jù)量的隨機(jī)讀取組成,文件的寫入則基 本上都是批量的追加寫,和偶爾的插入寫(GFS中還有大量的假設(shè),它們構(gòu)成了分布式文件系統(tǒng)架構(gòu)設(shè)計(jì)的基石。每一個(gè)系統(tǒng)架構(gòu)都是搭建在一定假設(shè)上的,這些 假設(shè)有些來自于實(shí)際業(yè)務(wù)的狀況,有些是因?yàn)樘焐臈l件約束,不基于假設(shè)理解設(shè)計(jì),肯定會(huì)有失偏頗...)。在GFS中,對(duì)文件的寫入分成追加寫和插入寫都 有所支持,但是,在HDFS中僅僅支持追加寫,這大大降低了復(fù)雜性。關(guān)于HDFS與GFS的一些不同,可以參看這里。。。

1. 文件和目錄的操作

文件目錄的信息,全部囤積在主控服務(wù)器上,因此,所有對(duì)文件目錄的操作,只會(huì)直接涉及到客戶端和主控服務(wù)器。整個(gè)目錄相關(guān)的操作流程基本都是這樣的:客戶端DFSClient調(diào)用ClientProtocol定義的相關(guān)函數(shù),該操作通過RPC傳送到其實(shí)現(xiàn)者主控服務(wù)器NameNode那里,NameNode做相關(guān)的處理后(很少...),調(diào)用FSNamesystem的相關(guān)函數(shù)。在FSNamesystem中,往往是做一些驗(yàn)證和租約操作,具體的目錄結(jié)構(gòu)操作交由FSDirectory的相應(yīng)函數(shù)來操作。最后,依次返回,經(jīng)由RPC傳送回客戶端。具體各操作涉及到的函數(shù)和具體步驟,參見下表:

相關(guān)操作 ClientProtocol / NameNode FSNamesystem FSDirectory 關(guān)鍵步驟
創(chuàng)建文件 create startFile addFile 1. 檢查是否有寫權(quán)限;
2. 檢查是否已經(jīng)存在此文件,如果是覆寫,則先進(jìn)行刪除操作;
3. 在指定路徑下添加INodeFileUnderConstruction的文件實(shí)例;
4. 寫日志;
5. 簽訂租約。
創(chuàng)建目錄 mkdirs mkdirs mkdirs 1. 檢查指定目錄是否是目錄;
2. 檢查是否有相關(guān)權(quán)限;
3. 在指定路徑的INode下,添加子節(jié)點(diǎn);
4. 寫日志。
改名操作 rename renameTo renameTo 1. 檢查相關(guān)路徑的權(quán)限;
2. 從老路徑下移除,在新路徑下添加;
3. 修改相關(guān)父路徑的修改時(shí)間;
4. 寫日志;
5. 將租約從老路徑移動(dòng)到新路徑下。
刪除操作 delete delete delete 1. 如果不是遞歸刪除,確認(rèn)指定路徑是否是空目錄;
2. 檢查相關(guān)權(quán)限;
3. 在目錄結(jié)構(gòu)上移除相關(guān)INode;
4. 修改父路徑的修改時(shí)間;
5. 將相關(guān)的數(shù)據(jù)塊,放入到廢棄隊(duì)列中去,等待處理;
6. 寫日志;
7. 廢棄相關(guān)路徑的租約。
設(shè)置權(quán)限 setPermission setPermission setPermission 1. 檢查owner判斷是否有操作權(quán)限;
2. 修改指定路徑下INode的權(quán)限;
3. 寫日志。
設(shè)置用戶 setOwner setOwner setOwner 1. 檢查是否有操作權(quán)限;
2. 修改指定路徑下INode的權(quán)限;
3. 寫日志。
設(shè)置時(shí)間 setTimes setTimes setTimes 1. 檢查是否有寫權(quán)限;
2. 修改指定路徑INode的時(shí)間信息;
3. 寫日志。

從上表可以看到,其實(shí)有的操作本質(zhì)上還是涉及 到了數(shù)據(jù)服務(wù)器,比如文件創(chuàng)建和刪除操作。但是,之前提到,主控服務(wù)器只于數(shù)據(jù)服務(wù)器是一個(gè)等待拉取的地位,它們不會(huì)主動(dòng)聯(lián)系數(shù)據(jù)服務(wù)器,將指令傳輸給它 們,而是放到相應(yīng)的數(shù)據(jù)結(jié)構(gòu)中,等待數(shù)據(jù)服務(wù)器來取。這樣的設(shè)計(jì),可以減少通信的次數(shù),加快操作的執(zhí)行速度。。。
另,上述步驟中,有些日志和租約相關(guān)的操作,從概念上來說,和目錄操作其實(shí)沒有任何聯(lián)系,但是,為了滿足分布式系統(tǒng)的需求,這些操作是非常有必要的,在此,按下不表。。。

2、文件的讀取

不論是文件讀取,還是文件的寫入,主控服務(wù)器扮演的都是中介的角色??蛻舳税炎约旱男枨筇峤唤o主控服務(wù)器,主控服務(wù)器挑選合適的數(shù)據(jù)服務(wù)器,介紹給客戶端,讓客戶端和數(shù)據(jù)服務(wù)器單聊,要讀要寫隨你們便。這種策略類似于DMA,降低了主控服務(wù)器的負(fù)載,提高了效率。。。
因此,在文件讀寫操作中,最主要的通信,發(fā)生在客戶端與數(shù)據(jù)服務(wù)器之間。它們之間跑的協(xié)議是ClientDatanodeProtocol。從這個(gè)協(xié)議中間,你無法看到和讀寫相關(guān)的接口,因?yàn)椋贖adoop中,讀寫操作是不走RPC機(jī)制的,而是另立門戶,獨(dú)立搭了一套通信框架。在數(shù)據(jù)服務(wù)器一端,DataNode類中有一個(gè)DataXceiverServer類的實(shí)例,它在一個(gè)單獨(dú)的線程等待請(qǐng)求,一旦接到,就啟動(dòng)一個(gè)DataXceiver的線程,處理此次請(qǐng)求。一個(gè)請(qǐng)求一個(gè)線程,對(duì)于數(shù)據(jù)服務(wù)器來說,邏輯上很簡(jiǎn)單。當(dāng)下,DataXceiver支持的請(qǐng)求類型有六種,具體的請(qǐng)求包和回復(fù)包格式,請(qǐng)參見這里,這里這里。在Hadoop的實(shí)現(xiàn)中,并沒有用類來封裝這些請(qǐng)求,而是按流的次序?qū)懴聛?,這給代碼閱讀帶來挺多的麻煩,也對(duì)代碼的維護(hù)帶來一定的困難,不知道是出于何種考慮。。。
相比于寫,文件的讀取實(shí)在是一個(gè)簡(jiǎn)單的過程。在客戶端DFSClient中,有一個(gè)DFSClient.DFSInputStream類。當(dāng)需要讀取一個(gè)文件的時(shí)候,會(huì)生成一個(gè)DFSInputStream的實(shí)例。它會(huì)先調(diào)用ClientProtocol定義getBlockLocations接口,提供給NameNode文件路徑、讀取位置、讀取長(zhǎng)度信息,從中取得一個(gè)LocatedBlocks類的對(duì)象,這個(gè)對(duì)象包含一組LocatedBlock,那里面有所規(guī)定位置中包含的所有數(shù)據(jù)塊信息,以及數(shù)據(jù)塊對(duì)應(yīng)的所有數(shù)據(jù)服務(wù)器的位置信息。當(dāng)讀取開始后,DFSInputStream會(huì)先嘗試從某個(gè)數(shù)據(jù)塊對(duì)應(yīng)的一組數(shù)據(jù)服務(wù)器中選出一個(gè),進(jìn)行連接。這個(gè)選取算法,在當(dāng)下的實(shí)現(xiàn)中,非常簡(jiǎn)單,就是選出第一個(gè)未掛的數(shù)據(jù)服務(wù)器,并沒有加入客戶端與數(shù)據(jù)服務(wù)器相對(duì)位置的考量。讀取的請(qǐng)求,發(fā)送到數(shù)據(jù)服務(wù)器后,自然會(huì)有DataXceiver來處理,數(shù)據(jù)被一個(gè)包一個(gè)包發(fā)送回客戶端,等到整個(gè)數(shù)據(jù)塊的數(shù)據(jù)都被讀取完了,就會(huì)斷開此鏈接,嘗試連接下一個(gè)數(shù)據(jù)塊對(duì)應(yīng)的數(shù)據(jù)服務(wù)器,整個(gè)流程,依次如此反復(fù),直到所有想讀的都讀取完了為止。。。

3、文件的寫入

文件讀取是一個(gè)一對(duì)一的過程,一個(gè)客戶端,只需要與一個(gè)數(shù)據(jù)服務(wù)器聯(lián)系,就可以獲得所需的內(nèi)容。但是,寫入操作,則是一個(gè)一對(duì)多的流程。一次寫入,需要在所有存放相關(guān)數(shù)據(jù)塊的數(shù)據(jù)服務(wù)器都保持同步的更新,有任何的差池,整個(gè)流程就告失敗。。。
在分布式系統(tǒng)中,一旦涉及到寫入操作,并發(fā)處 理難免都會(huì)淪落成為一個(gè)變了相的串行操作。因?yàn)?,如果不同的客戶端如果是任意時(shí)序并發(fā)寫入的話,整個(gè)寫入的次序無法保證,可能你寫半條記錄我寫半條記錄, 最后出來的結(jié)果亂七八糟不可估量。在HDFS中,并發(fā)寫入的次序控制,是由主控服務(wù)器來把握的。當(dāng)創(chuàng)建、續(xù)寫一個(gè)文件的時(shí)候,該文件的節(jié)點(diǎn)類,由INodeFile升級(jí)成為INodeFileUnderConstruction,INodeFileUnderConstruction 是INodeFile的子類,它起到一個(gè)鎖的作用。如果當(dāng)一個(gè)客戶端想創(chuàng)建或續(xù)寫的文件是INodeFileUnderConstruction,會(huì)引發(fā) 異常,因?yàn)檫@說明這個(gè)此處有爺,請(qǐng)另尋高就,從而保持了并發(fā)寫入的次序性。同時(shí),INodeFileUnderConstruction有包含了此時(shí)正在 操作它的客戶端的信息以及最后一個(gè)數(shù)據(jù)塊的數(shù)據(jù)服務(wù)器信息,當(dāng)追加寫的時(shí)候可以更快速的響應(yīng)。。。
與讀取類似,DFSClient也有一個(gè)DFSClient.DFSOutputStream類,寫入開始,會(huì)創(chuàng)建此類的實(shí)例。DFSOutputStream會(huì)從NameNode上拿一個(gè)LocatedBlock,這里面有最后一個(gè)數(shù)據(jù)塊的所有數(shù)據(jù)服務(wù)器的信息。這些數(shù)據(jù)服務(wù)器每一個(gè)都需要能夠正常工作(對(duì)于讀取,只要還有一個(gè)能工作的就可以實(shí)現(xiàn)...),它們會(huì)依照客戶端的位置被排列成一個(gè)有著最近物理距離和最小的序列(物理距離,是根據(jù)機(jī)器的位置定下來的...),這個(gè)排序問題類似于著名旅行商問題,屬于NP復(fù)雜度,但是由于服務(wù)器數(shù)量不多,所以用最粗暴的算法,也并不會(huì)看上去不美。。。
文件寫入,就是在這一組數(shù)據(jù)服務(wù)器上構(gòu)造成數(shù)據(jù)流的雙向流水線。 DFSOutputStream,會(huì)與序列的第一個(gè)數(shù)據(jù)服務(wù)器建立Socket連接,發(fā)送請(qǐng)求頭,然后等待回應(yīng)。DataNode同樣是建立 DataXceiver來處理寫消息,DataXceiver會(huì)依照包中傳過來的其他服務(wù)器的信息,建立與下一個(gè)服務(wù)器的連接,并生成類似的頭,發(fā)送給 它,并等待回包。此流程依次延續(xù),直到最后一級(jí),它發(fā)送回包,反向著逐級(jí)傳遞,再次回到客戶端。如果一切順利,那么此時(shí),流水線建立成功,開始正式發(fā)送數(shù) 據(jù)。數(shù)據(jù)是分成一個(gè)個(gè)數(shù)據(jù)包發(fā)送的,所有寫入的內(nèi)容,被緩存在客戶端,當(dāng)寫滿64K,會(huì)被封裝成DFSOutputStream.Packet類實(shí)例,放入DFSOutputStream的dataQueue隊(duì)列。DFSOutputStream.DataStreamer會(huì)時(shí)刻監(jiān)聽這個(gè)隊(duì)列,一旦不為空,則開始發(fā)送,將位于dataQueue隊(duì)首的包移動(dòng)到ackQueue隊(duì)列的隊(duì)尾,表示已發(fā)送但尚未接受回復(fù)的包隊(duì)列。同時(shí)啟動(dòng)ResponseProcessor線程監(jiān)聽回包,直到收到相應(yīng)回包,才將發(fā)送包從ackQueue中移除,表示成功。每一個(gè)數(shù)據(jù)服務(wù)器的DataXceiver收到了數(shù)據(jù)包,一邊寫入到本地文件中去,一邊轉(zhuǎn)發(fā)給下一級(jí)的數(shù)據(jù)服務(wù)器,等待回包,同前面建立流水線的流程。。。
當(dāng)一個(gè)數(shù)據(jù)塊寫滿了之后,客戶端需要向主控服務(wù)器申請(qǐng)追加新的數(shù)據(jù)塊。這個(gè)會(huì)引起一次數(shù)據(jù)塊的分配,成功后,會(huì)將新的數(shù)據(jù)服務(wù)器組返還給客戶端。然后重新回到上述流程,繼續(xù)前行。。。
關(guān)于寫入的流程,還可以參見這里。此外,寫入涉及到租約問題,后續(xù)會(huì)仔細(xì)的來說。。。

IV. 分布式支持

如果單機(jī)的文件系統(tǒng)是田里勤懇的放牛娃,那么 分布式文件系統(tǒng)就是刀尖上討飯吃的馬賊了。在分布式環(huán)境中,有太多的意外,數(shù)據(jù)隨時(shí)傳輸錯(cuò)誤,服務(wù)器時(shí)刻準(zhǔn)備犧牲,很多平常稱為異常的現(xiàn)象,在這里都需要 按照平常事來對(duì)待。因此,對(duì)于分布式文件系統(tǒng)而言,僅僅是滿足了正常狀況下文件系統(tǒng)各項(xiàng)服務(wù)還不夠,還需要保證分布式各種意外場(chǎng)景下健康持續(xù)的服務(wù),否 則,將一無是處。。。

1、服務(wù)器的錯(cuò)誤恢復(fù)

在分布式環(huán)境中,哪臺(tái)服務(wù)器犧牲都是常見的事情,犧牲不可怕,可怕的是你都沒有時(shí)刻準(zhǔn)備好它們會(huì)犧牲。作為一個(gè)合格的分布式系統(tǒng),HDFS當(dāng)然時(shí)刻準(zhǔn)備好了前赴后繼奮勇向前。HDFS有三類服務(wù)器,每一類服務(wù)器出錯(cuò)了,都有相應(yīng)的應(yīng)急策略。。。
a. 客戶端
生命最輕如鴻毛的童鞋,應(yīng)該就是客戶端了。畢 竟,做為一個(gè)文件系統(tǒng)的使用者,在整個(gè)文件系統(tǒng)中的地位,難免有些歸于三流。而作為客戶端,大部分時(shí)候,犧牲了就犧牲了,沒人哀悼,無人同情,只有在在辛 勤寫入的時(shí)候,不幸辭世(機(jī)器掛了,或者網(wǎng)絡(luò)斷了,諸如此類...),才會(huì)引起些恐慌。因?yàn)?,此時(shí)此刻,在主控服務(wù)器上對(duì)應(yīng)的文件,正作為INodeFileUnderConstruction活 著,僅僅為占有它的那個(gè)客戶端服務(wù)者,做為一個(gè)專一的文件,它不允許別的客戶端染指。這樣的話,一旦占有它的客戶端服務(wù)者犧牲了,此客戶端會(huì)依然占著茅坑 不拉屎,讓如花似玉INodeFileUnderConstruction孤孤單單守寡終身。這種事情當(dāng)然無法容忍,因此,必須有辦法解決這個(gè)問題,辦法 就是:租約。。。
租約,顧名思義,就是當(dāng)客戶端需要占用某文件的時(shí)候,與主控服務(wù)器簽訂的一個(gè)短期合同。這個(gè)合同有一個(gè)期限,在這個(gè)期限內(nèi),客戶端可以延長(zhǎng)合同期限,一旦超過期限,主控服務(wù)器會(huì)強(qiáng)行終止此租約,將這個(gè)文件的享用權(quán),分配給他人。。。
在打開或創(chuàng)建一個(gè)文件,準(zhǔn)備追加寫之前,會(huì)調(diào)用LeaseManageraddLease方法,在指定的路徑下與此客戶端簽訂一份租約。客戶端會(huì)啟動(dòng)DFSClient.LeaseChecker線程,定時(shí)輪詢調(diào)用ClientProtocolrenewLease方法,續(xù)簽租約。在主控服務(wù)器一端,有一個(gè)LeaseManager.Monitor線程,始終在輪詢檢查所有租約,查看是否有到期未續(xù)的租約。如果一切正常,該客戶端完成寫操作,會(huì)關(guān)閉文件,停止租約,一旦有所意外,比如文件被刪除了,客戶端犧牲了,主控服務(wù)器都會(huì)剝奪此租約,如此,來避免由于客戶端停機(jī)帶來的資源被長(zhǎng)期霸占的問題。。。
b. 數(shù)據(jù)服務(wù)器
當(dāng)然,會(huì)掛的不只是客戶端,海量的數(shù)據(jù)服務(wù)器 是一個(gè)更不穩(wěn)定的因素。一旦某數(shù)據(jù)服務(wù)器犧牲了,并且主控服務(wù)器被蒙在鼓中,主控服務(wù)器就會(huì)變相的欺騙客戶端,給它們無法連接的讀寫服務(wù)器列表,導(dǎo)致它們 處處碰壁無法工作。因此,為了整個(gè)系統(tǒng)的穩(wěn)定,數(shù)據(jù)服務(wù)器必須時(shí)刻向主控服務(wù)器匯報(bào),保持主控服務(wù)器對(duì)其的完全了解,這個(gè)機(jī)制,就是心跳消息。在HDFS 中,主控服務(wù)器NameNode實(shí)現(xiàn)了DatanodeProtocol接口,數(shù)據(jù)服務(wù)器DataNode會(huì)在主循環(huán)中,不停的調(diào)用該協(xié)議中的sendHeartbeat方 法,向NameNode匯報(bào)狀況。在此調(diào)用中,DataNode會(huì)將其整體運(yùn)行狀況告知NameNode,比如:有多少可用空間、用了多大的空間,等等之 類。NameNode會(huì)記住此DataNode的運(yùn)行狀況,作為新的數(shù)據(jù)塊分配或是負(fù)載均衡的依據(jù)。當(dāng)NameNode處理完成此消息后,會(huì)將相關(guān)的指令 封裝成一個(gè)DatanodeCommand對(duì)象,交還給DataNode,告訴數(shù)據(jù)服務(wù)器什么數(shù)據(jù)塊要?jiǎng)h除什么數(shù)據(jù)塊要新增等等之類,數(shù)據(jù)服務(wù)器以此為自己的行動(dòng)依據(jù)。。。
但是,sendHeartbeat并沒有提供本地的數(shù)據(jù)塊信息給NameNode,那么主控服務(wù)器就無法知道此數(shù)據(jù)服務(wù)器應(yīng)該分配什么數(shù)據(jù)塊應(yīng)該刪除什么數(shù)據(jù)塊,那么它是如何決定的呢?答案就是DatanodeProtocol定義的另一個(gè)方法,blockReport。 DataNode也是在主循環(huán)中定時(shí)調(diào)用此方法,只是,其周期通常比調(diào)用sendHeartbeat的更長(zhǎng)。它會(huì)提交本地的所有數(shù)據(jù)塊狀況給 NameNode,NameNode會(huì)和本地保存的數(shù)據(jù)塊信息比較,決定什么該刪除什么該新增,并將相關(guān)結(jié)果緩存在本地對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)中,等待此服務(wù)器再 發(fā)送sendHeartbeat消息過來的時(shí)候,依照這些數(shù)據(jù)結(jié)構(gòu)中的內(nèi)容,做出相應(yīng)的DatanodeCommand指令。blockReport方法 同樣也會(huì)返回一個(gè)DatanodeCommand給DataNode,但通常,只是為空(只有出錯(cuò)的時(shí)候不為空),我想,增加緩存,也許是為了確保每個(gè)指 令都可以重復(fù)發(fā)送并確定被執(zhí)行。。。
c. 主控服務(wù)器
當(dāng)然,作為整個(gè)系統(tǒng)的核心和單點(diǎn),含辛茹苦的主控服務(wù)器含淚西去,整個(gè)分布式文件服務(wù)集群將徹底癱瘓罷工。如何在主控服務(wù)器犧牲后,提拔新的主控服務(wù)器并迅速使其進(jìn)入工作角色,就成了系統(tǒng)必須考慮的問題。解決策略就是:日志。。。
其實(shí)這并不是啥新鮮東西,一看就知道是從數(shù)據(jù)庫那兒偷師而來的。在主控服務(wù)器上,所有對(duì)文件目錄操作的關(guān)鍵步驟(具體文件內(nèi)容所處的數(shù)據(jù)服務(wù)器,是不會(huì)被 寫入日志的,因?yàn)檫@些內(nèi)容是動(dòng)態(tài)建立的...),都會(huì)被寫入日志。另外,主控服務(wù)器會(huì)在某些時(shí)刻,將當(dāng)下的文件目錄完整的序列化到本地,這稱為鏡像。一旦存有鏡像,鏡像前期所寫的日志和其他鏡像,都純屬冗余,其歷史使命已經(jīng)完成,可以報(bào)廢刪除了。在主控服務(wù)器不幸犧牲,或者是戰(zhàn)略性的停機(jī)修整結(jié)束,并重新啟動(dòng)后,主控服務(wù)器會(huì)根據(jù)最近的鏡像 + 鏡像之后的所有日志,重建整個(gè)文件目錄,迅速將服務(wù)能力恢復(fù)到犧牲前的水準(zhǔn)。。。
對(duì)于數(shù)據(jù)服務(wù)器而言,它們會(huì)通過一些手段,迅速得知頂頭上司的更迭消息。它們會(huì)立刻轉(zhuǎn)投新東家的名下,在新東家旗下注冊(cè),并開始向其發(fā)送心跳消息,這個(gè)機(jī)制,可能用分布式協(xié)同服務(wù)來實(shí)現(xiàn),這里不說也罷。。。
在HDFS的實(shí)現(xiàn)中,FSEditLog類是整個(gè)日志體系的核心,提供了一大堆方便的日志寫入API,以及日志的恢復(fù)存儲(chǔ)等功能。目前,它支持若干種日志類型,都冠以O(shè)P_XXX,并提供相關(guān)API,具體可以參見這里。為了保證日志的安全性,F(xiàn)SEditLog提供了EditLogFileOutputStream類作為寫入的承載類,它會(huì)同時(shí)開若干個(gè)本地文件,然后依次寫入,防止日志的損壞導(dǎo)致不可估量的后果。在FSEditLog上面,有一個(gè)FSImage類, 存儲(chǔ)文件鏡像并調(diào)用FSEditLog對(duì)外提供相關(guān)的日志功能。FSImage是Storage類的子類,如果對(duì)數(shù)據(jù)塊的講述有所印象的話,你可以回憶起 來,凡事從此類派生出來的東西,都具有版本性質(zhì),可以進(jìn)行升級(jí)和回滾等等,以此,來實(shí)現(xiàn)產(chǎn)生鏡像是對(duì)原有日志和鏡像處理的復(fù)雜邏輯。。。
目前,在HDFS的日志系統(tǒng)中,有些地方與 GFS的描述有所不同。在HDFS中,所有日志文件和鏡像文件都是本地文件,這就相當(dāng)于,把日志放在自家的保險(xiǎn)箱中,一旦主控服務(wù)器掛了,別的后繼而上的 服務(wù)器也無法拿到這些日志和鏡像,用于重振雄風(fēng)。因此,在HDFS中,運(yùn)行著一個(gè)SecondaryNameNode服務(wù)器,它做為主控服務(wù)器的替補(bǔ),隱忍厚積薄發(fā)為篡位做好準(zhǔn)備,其中,核心內(nèi)容就是:定期下載并處理日志和鏡像。SecondaryNameNode看上去像客戶端一樣,與NameNode之間,走著NamenodeProtocol協(xié)議。它會(huì)不停的查看主控服務(wù)器上面累計(jì)日志的大小,當(dāng)達(dá)到閾值后,調(diào)用doCheckpoint函數(shù),此函數(shù)的主要步驟包括:
  • 首先是調(diào)用startCheckpoint做一些本地的初始化工作;
  • 然后調(diào)用rollEditLog,將NameNode上此時(shí)操作的日志文件從edit切到edit.new上來,這個(gè)操作瞬間完成,上層寫日志的函數(shù)完全感覺不到差別;
  • 接著,調(diào)用downloadCheckpointFiles,將主控服務(wù)器上的鏡像文件和日志文件都下載到此候補(bǔ)主控服務(wù)器上來;
  • 并調(diào)用doMerge,打開鏡像和日志,將日志生成新的鏡像,保存覆蓋;
  • 下一步,調(diào)用putFSImage把新的鏡像上傳回NameNode;
  • 再調(diào)用rollFsImage,將鏡像換成新的,在日志從edit.new改名為edit;
  • 最后,調(diào)用endCheckpoint做收尾工作。
整個(gè)算法涉及到NameNode和SecondaryNameNode兩個(gè)服務(wù)器,最終結(jié)果是NameNode和SecondaryNameNode都依照算法進(jìn)行前的日志生成了鏡像。而兩個(gè)服務(wù)器上日志文件的內(nèi)容,前者是整個(gè)算法進(jìn)行期間所寫的日志,后者始終不會(huì)有任何日志。當(dāng)主控服務(wù)器犧牲的時(shí)候,運(yùn)行SecondaryNameNode的服務(wù)器立刻被扶正,在其上啟動(dòng)主控服務(wù),利用其日志和鏡像,恢復(fù)文件目錄,并逐步接受各數(shù)據(jù)服務(wù)器的注冊(cè),最終向外提供穩(wěn)定的文件服務(wù)。。。
同樣的事情,GFS采用的可能是另外一個(gè)策略,就是在寫日志的時(shí)候,并不局限在本地,而是同時(shí)書寫網(wǎng)絡(luò)日志,即在若干個(gè)遠(yuǎn)程服務(wù)器上生成同樣的日志。然后,在某些時(shí)機(jī),主控服務(wù)器自己,生成鏡像,降低日志規(guī)模。當(dāng)主控服務(wù)器犧牲,可以在擁有網(wǎng)絡(luò)日志的服務(wù)器上啟動(dòng)主控服務(wù),升級(jí)成為主控服務(wù)器。。。
GFS與HDFS的策略相比較,前者是化整為零,后者則是批量處理,通常我們認(rèn)為,批量處理的平均效率更高一些,且相對(duì)而言,可能實(shí)現(xiàn)起來容易一些,但是,由于有間歇期,會(huì)導(dǎo)致日志的丟失,從而無法100%的將備份主控服務(wù)器的狀態(tài)與主控服務(wù)器完全同步。。。

2、數(shù)據(jù)的正確性保證

在復(fù)雜紛繁的分布式環(huán)境中,我們堅(jiān)定的相信, 萬事皆有可能。哪怕各個(gè)服務(wù)器都舒舒服服的活著,也可能有各種各樣的情況導(dǎo)致網(wǎng)絡(luò)傳輸中的數(shù)據(jù)丟失或者錯(cuò)誤。并且在分布式文件系統(tǒng)中,同一份文件的數(shù)據(jù), 是存在大量冗余備份的,系統(tǒng)必須要維護(hù)所有的數(shù)據(jù)塊內(nèi)容完全同步,否則,一人一言,不同客戶端讀同一個(gè)文件讀出不同數(shù)據(jù),用戶非得瘋了不可。。。
在HDFS中,為了保證數(shù)據(jù)的正確性和同一份數(shù)據(jù)的一致性,做了大量的工作。首先,每一個(gè)數(shù)據(jù)塊,都有一個(gè)版本標(biāo)識(shí),在Block類中,用一個(gè)長(zhǎng)整型的數(shù)generationStamp來表示版本信息(Block類是所有表示數(shù)據(jù)塊的數(shù)據(jù)結(jié)構(gòu)的基類),一旦數(shù)據(jù)塊上的數(shù)據(jù)有所變化,此版本號(hào)將向前增加。 在主控服務(wù)器上,保存有此時(shí)每個(gè)數(shù)據(jù)塊的版本,一旦出現(xiàn)數(shù)據(jù)服務(wù)器上相關(guān)數(shù)據(jù)塊版本與其不一致,將會(huì)觸發(fā)相關(guān)的恢復(fù)流程。這樣的機(jī)制保證了各個(gè)數(shù)據(jù)服務(wù)器 器上的數(shù)據(jù)塊,在基本大方向上都是一致的。但是,由于網(wǎng)絡(luò)的復(fù)雜性,簡(jiǎn)單的版本信息無法保證具體內(nèi)容的一致性(因?yàn)榇税姹拘畔⑴c內(nèi)容無關(guān),可能會(huì)出現(xiàn)版本 相同,但內(nèi)容不同的狀況)。因此,為了保證數(shù)據(jù)內(nèi)容上的一致,必須要依照內(nèi)容,作出簽名。。。
當(dāng)客戶端向數(shù)據(jù)服務(wù)器追加寫入數(shù)據(jù)包時(shí),每一個(gè)數(shù)據(jù)包的數(shù)據(jù),都會(huì)切分成512字節(jié)大小的段,作為簽名驗(yàn)證的基本單位,在HDFS中,把這個(gè)數(shù)據(jù)段稱為Chunk,即傳輸塊(注意,在GFS中,Chunk表達(dá)的是數(shù)據(jù)塊...)。在每一個(gè)數(shù)據(jù)包中,都包含若干個(gè)傳輸塊以及每一個(gè)傳輸塊的簽名,當(dāng)下,這個(gè)簽名是根據(jù)Java SDK提供的CRC算法算得的,其實(shí)就是一個(gè)奇偶校驗(yàn)。當(dāng)數(shù)據(jù)包傳輸?shù)搅魉€的最后一級(jí),數(shù)據(jù)服務(wù)器會(huì)對(duì)其進(jìn)行驗(yàn)證(想一想,為什么只在最后一級(jí)做驗(yàn)證,而不是每級(jí)都做...),一旦發(fā)現(xiàn)當(dāng)前的傳輸塊簽名與在客戶端中的簽名不一致,整個(gè)數(shù)據(jù)包的寫入被視為無效,Lease Recover(租約恢復(fù))算法被觸發(fā)。。。
從基本原理上看,這個(gè)算法很簡(jiǎn)單,就是取所有數(shù)據(jù)服務(wù)器上此數(shù)據(jù)塊的最小長(zhǎng)度當(dāng)作正確內(nèi)容的長(zhǎng)度,將其他數(shù)據(jù)服務(wù)器上此數(shù)據(jù)塊超出此長(zhǎng)度的部分切除。 從正確性上看,此算法無疑是正確的,因?yàn)橹辽儆幸粋€(gè)數(shù)據(jù)服務(wù)器會(huì)發(fā)現(xiàn)此錯(cuò)誤,并拒絕寫入,那么,如果寫入了的,都是正確的;從效率上看,此算法也是高效 的,因?yàn)樗苊饬酥貜?fù)的傳輸和復(fù)雜的驗(yàn)證,僅僅是各自刪除尾部的一些內(nèi)容即可。但從具體實(shí)現(xiàn)上來看,此算法稍微有些繞,因?yàn)?,為了降低本已不堪重?fù)的主控 服務(wù)器的負(fù)擔(dān),此算法不是由主控服務(wù)器這個(gè)大腦發(fā)起的,而是通過選舉一個(gè)數(shù)據(jù)服務(wù)器作為Primary,由Primary發(fā)起,通過調(diào)用與其他各數(shù)據(jù)服務(wù)器間的InterDatanodeProtocol協(xié)議,最終完成的。具體的算法流程,參見LeaseManager類上面的注釋。需要說明的是此算法的觸發(fā)時(shí)機(jī)和發(fā)起者。此算法可以由客戶端或者是主控服務(wù)器發(fā) 起,當(dāng)客戶端在寫入一個(gè)數(shù)據(jù)包失敗后,會(huì)發(fā)起租約恢復(fù)。因?yàn)?,一次寫入失敗,不論是何種原因,很有可能就會(huì)導(dǎo)致流水線上有的服務(wù)器寫了,有的沒寫,從而造 成不統(tǒng)一。而主控服務(wù)器發(fā)起的時(shí)機(jī),則是在占有租約的客戶端超出一定時(shí)限沒有續(xù)簽,這說明客戶端可能掛了,在臨死前可能干過不利于數(shù)據(jù)塊統(tǒng)一的事情,作為 監(jiān)督者,主控服務(wù)器需要發(fā)起一場(chǎng)恢復(fù)運(yùn)動(dòng),確保一切正確。。。

3、負(fù)載均衡

負(fù)載的均衡,是分布式系統(tǒng)中一個(gè)永恒的話題, 要讓大家各盡其力齊心干活,發(fā)揮各自獨(dú)特的優(yōu)勢(shì),不能忙得忙死閑得閑死,影響戰(zhàn)斗力。而且,負(fù)載均衡也是一個(gè)復(fù)雜的問題,什么是均衡,是一個(gè)很模糊的概 念。比如,在分布式文件系統(tǒng)中,總共三百個(gè)數(shù)據(jù)塊,平均分配到十個(gè)數(shù)據(jù)服務(wù)器上,就算均衡了么?其實(shí)不一定,因?yàn)槊恳粋€(gè)數(shù)據(jù)塊需要若干個(gè)備份,各個(gè)備份的 分布應(yīng)該充分考慮到機(jī)架的位置,同一個(gè)機(jī)架的服務(wù)器間通信速度更快,而分布在不同機(jī)架則更具有安全性,不會(huì)在一棵樹上吊死。。。
在這里說的負(fù)載均衡,是寬泛意義上的均衡過程,主要涵蓋兩個(gè)階段的事務(wù),一個(gè)是在任務(wù)初始分配的時(shí)候盡可能合理分配,另一個(gè)是在事后時(shí)刻監(jiān)督及時(shí)調(diào)整。。。
在HDFS中,ReplicationTargetChooser類, 是負(fù)責(zé)實(shí)現(xiàn)為新分配的數(shù)據(jù)塊尋找婆家的?;旧蟻碚f,數(shù)據(jù)塊的分配工作和備份的數(shù)量、申請(qǐng)的客戶端地址(也就是寫入者)、已注冊(cè)的數(shù)據(jù)服務(wù)器位置,密切相 關(guān)。其算法基本思路是只考量靜態(tài)位置信息,優(yōu)先照顧寫入者的速度,讓多份備份分配到不同的機(jī)架去。具體算法,自行參見源碼。此外,HDFS的Balancer類,是為了實(shí)現(xiàn)動(dòng)態(tài)的負(fù)載調(diào)整而存在的。Balancer類派生于Tool類,這說明,它是以一個(gè)獨(dú)立的進(jìn)程存在的,可以獨(dú)立的運(yùn)行和配置。它運(yùn)行有NamenodeProtocolClientProtocol兩個(gè)協(xié)議,與主控服務(wù)器進(jìn)行通信,獲取各個(gè)數(shù)據(jù)服務(wù)器的負(fù)載狀況,從而進(jìn)行調(diào)整。主要的調(diào)整其實(shí)就是一個(gè)操作,將一個(gè)數(shù)據(jù)塊從一個(gè)服務(wù)器搬遷到另一個(gè)服務(wù)器上。Balancer會(huì)向相關(guān)的目標(biāo)數(shù)據(jù)服務(wù)器發(fā)出一個(gè)DataTransferProtocol.OP_REPLACE_BLOCK消息,接收到這個(gè)消息的數(shù)據(jù)服務(wù)器,會(huì)將數(shù)據(jù)塊寫入本地,成功后,通知主控服務(wù)器,刪除早先的那個(gè)數(shù)據(jù)服務(wù)器上的同一塊數(shù)據(jù)塊。具體的算法請(qǐng)自行參考源碼。。。

4、垃圾回收

對(duì)于垃圾,大家應(yīng)該耳熟能詳了,在分布式文件系統(tǒng)而言,沒有利用價(jià)值的數(shù)據(jù)塊備份,就是垃圾。在現(xiàn)實(shí)生活中,我們提倡垃圾分類,為了更好的理解分布式文件系統(tǒng)的垃圾收集,搞個(gè)分類也是很有必要的。基本上,所有的垃圾都可以視為兩類,一類是由系統(tǒng)正常邏輯產(chǎn)生的,比如某個(gè)文件被刪除了,所有相關(guān)的數(shù)據(jù)塊都淪為垃圾了,某個(gè)數(shù)據(jù)塊被負(fù)載均衡器移動(dòng)了,原始數(shù)據(jù)塊也不幸成了垃圾了。此類垃圾最大的特點(diǎn),就是主控服務(wù)器是生成垃圾的罪魁禍?zhǔn)?/strong>,也就是說主控服務(wù)器完全了解有哪些垃圾需要處理。另外還有一類垃圾,是由于系統(tǒng)的一些異常癥狀產(chǎn)生的,比如某個(gè)數(shù)據(jù)服務(wù)器停機(jī)了一段,重啟之后發(fā)現(xiàn)其上的某個(gè)數(shù)據(jù)塊已經(jīng)在其他服務(wù)器上重新增加了此數(shù)據(jù)塊的備份,它上面的那個(gè)備份過期了失去價(jià)值了,需要被當(dāng)作垃圾來處理了。此類垃圾的特點(diǎn)恰恰相反,主控服務(wù)器無法直接了解到垃圾狀況,需要曲線救國(guó)。。。
在HDFS中,第一類垃圾的判定自然很容易,在一些正常的邏輯中產(chǎn)生的垃圾,全部被塞進(jìn)了FSNamesystemrecentInvalidateSets這 個(gè)Map中。而第二類垃圾的判定,則放在數(shù)據(jù)服務(wù)器發(fā)送其數(shù)據(jù)塊信息來的過程中,經(jīng)過與本地信息的比較,可以斷定,此數(shù)據(jù)服務(wù)器上有哪些數(shù)據(jù)塊已經(jīng)不幸淪 為垃圾。同樣,這些垃圾也被塞到recentInvalidateSets中去。在與數(shù)據(jù)服務(wù)器進(jìn)行心跳交流的過程中,主控服務(wù)器會(huì)將它上面有哪些數(shù)據(jù)塊 需要?jiǎng)h除,數(shù)據(jù)服務(wù)器對(duì)這些數(shù)據(jù)塊的態(tài)度是,直接物理刪除。在GFS的論文中,對(duì)如何刪除一個(gè)數(shù)據(jù)塊有著不同的理解,它覺著應(yīng)該先緩存起來,過幾天沒人想恢復(fù)它了再刪除。在HDFS的文檔中,則明確表示,在現(xiàn)行的應(yīng)用場(chǎng)景中,沒有需要這個(gè)需求的地方,因此,直接刪除就完了。這說明,理念是一切分歧的根本:)。。。

V. 總結(jié)

整個(gè)分布式文件系統(tǒng),計(jì)算系統(tǒng),數(shù)據(jù)庫系統(tǒng)的 設(shè)計(jì)理念,基本是一脈相承的。三類服務(wù)器、作為單點(diǎn)存在的核心控制服務(wù)器、基于日志的恢復(fù)機(jī)制、基于租約的保持聯(lián)系機(jī)制、等等,在后續(xù)分布式計(jì)算系統(tǒng)和分 布式數(shù)據(jù)庫中都可以看到類似的影子,在分布式文件系統(tǒng)這里,我詳述了這些內(nèi)容,可能在后續(xù)就會(huì)默認(rèn)知道而說的比較簡(jiǎn)略了。而刨去這一些,分布式文件系統(tǒng)中 最大特點(diǎn),就是文件塊的冗余存儲(chǔ),它直接導(dǎo)致了較為復(fù)雜的寫入流程。當(dāng)然,雖說分布式文件系統(tǒng)在分布式計(jì)算和數(shù)據(jù)庫中都有用到,但如果對(duì)其機(jī)理沒有興趣, 只要把它當(dāng)成是一個(gè)可以在任何機(jī)器上使用的文件系統(tǒng),就不會(huì)對(duì)其他上層建筑的理解產(chǎn)生障礙。。。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多