??Google File System(簡稱GFS)是適用于大規(guī)模且可擴(kuò)展的分布式文件系統(tǒng)膝蜈,可以部署在廉價(jià)的商務(wù)服務(wù)器上鹦蠕,在保證系統(tǒng)可靠性和可用 性的同時(shí),大大降低了系統(tǒng)的成本捏雌。GFS的設(shè)計(jì)目標(biāo)是高性能、高可靠囱晴、高可用性。
??GFS把機(jī)器故障視為正称靶唬現(xiàn)象畸写,可以很好地處理系統(tǒng)故障。GFS系統(tǒng)通常會(huì)部署在上百臺(tái)甚至上千臺(tái)廉價(jià)服務(wù)器上氓扛,并會(huì)有相當(dāng)多臺(tái)廉價(jià)服務(wù)器上部署GFS Client來訪問GFS服務(wù)枯芬,所以應(yīng)用故障、操作系統(tǒng)bug采郎、連接故障千所、網(wǎng)絡(luò)故障、甚至機(jī)器供電故障都是經(jīng)常發(fā)生的故障蒜埋。GFS系統(tǒng)可以支持系統(tǒng)監(jiān)控淫痰、故障檢測、故障容忍和自動(dòng)恢復(fù)整份,提供了非常高的可靠性待错。其次,GFS系統(tǒng)中的文件一般都是大文件烈评,且文件操作大部分場景下都是append而不是overwrite火俄。一旦文件寫入完成后,大部分操作都是讀文件且是順序讀础倍。
??GFS提供了非標(biāo)準(zhǔn)(比如POSIX)的文件系統(tǒng)接口,支持 create胎挎、delete沟启、open、close犹菇、read以及write德迹。另外GFS支持snapshot和record append操作。snapshot可以以很低的代價(jià)創(chuàng)建文件或者目錄樹的拷貝揭芍,record append可以支持多個(gè)client并發(fā)地向同一個(gè)文件append data胳搞,同時(shí)還能保證每個(gè)client的append操作的原子性。
一称杨、GFS架構(gòu)
??GFS系統(tǒng)包括master肌毅、多個(gè)chunkserver以及多個(gè)client。文件被切分為固定大小的小文件(chunk)姑原。每個(gè)chunk創(chuàng)建時(shí)悬而,master會(huì)分配一個(gè)64bit的全局唯一且不可修改的chunk handler來標(biāo)志這個(gè)chunk。chunkserver負(fù)責(zé)將chunk存儲(chǔ)在本地磁盤的Linux文件中锭汛,并通過chunk hander和byte range來讀寫chunk文件笨奠。為了提高可靠性袭蝗,每個(gè)chunk都是多副本存儲(chǔ)在多個(gè)chunkserver上,默認(rèn)情況下是三副本般婆。用戶可以為不同名字空間下的文件配置不同的副本數(shù)到腥。??master記錄了文件系統(tǒng)的metadata,包括名字空間蔚袍、權(quán)限控制信息乡范、文件到chunk的mapping以及chunk的分布。master也負(fù)責(zé)chunk的lease管理页响、無用chunk的垃圾回收篓足、chunk遷移等。master定期與chunkserver通信闰蚕,向chunkserver發(fā)送指令并搜集chunkserver的狀態(tài)栈拖。GFS client通過GFS的API與GFS系統(tǒng)通信(讀寫數(shù)據(jù))。client向master請求獲取metadata没陡,真正的讀寫數(shù)據(jù)是直接與chunkserver交互涩哟。client和chunkserver都不cache文件數(shù)據(jù)。因?yàn)榇蟛糠謶?yīng)用都是基于API來streaming read 大文件且系統(tǒng)的文件數(shù)據(jù)太多盼玄,所以client緩存文件數(shù)據(jù)沒有意義贴彼。chunkserver所在機(jī)器的Linux的buffer cache以及cache了頻繁訪問的數(shù)據(jù),chunkserver也是沒有去cache文件數(shù)據(jù)的埃儿。
二器仗、Single Master
??單點(diǎn)master大大簡化了系統(tǒng)設(shè)計(jì),因?yàn)閙aster知曉所有的meta信息童番,所以可以執(zhí)行更加復(fù)雜的chunk位置分配和副本策略精钮。但是,在讀寫數(shù)據(jù)時(shí)必須降低master的參與剃斧,以避免單點(diǎn)的master稱為系統(tǒng)瓶頸轨香。client不會(huì)通過master來讀寫文件數(shù)據(jù)奸忽,但是client會(huì)向master發(fā)送查詢chunk位置分布的請求俯抖,然后client端緩存chunk的分布信息,然后直接向chunkserver讀寫數(shù)據(jù)范删。大致的讀過程如下:
1根蟹、client根據(jù)文件名脓杉、byte offset以及chunk size計(jì)算出要讀取的文件的chunk index
2、client通過文件名简逮、chunk index向master查詢chunk的分布
3丽已、master回復(fù)chunk handler以及副本分布
4、client 緩存chunk的meta信息买决,key由文件名和chunk index組成
5沛婴、client從chunk的分布信息中查找距離自己最新的chunkserver吼畏,并發(fā)送查詢請求。查詢請求中包括chunk hander以及byte range嘁灯。后續(xù)對相同chunk的查詢不需要再次向master查詢meta信息泻蚊,因?yàn)閏lient已經(jīng)緩存了meta信息。
三丑婿、chunk size
??chunk size是GFS系統(tǒng)的關(guān)鍵參數(shù)性雄,通常設(shè)置為64MB,遠(yuǎn)大于文件系統(tǒng)的block大小羹奉。每個(gè)chunk的副本都chunkserver所在機(jī)器上以Linux file存儲(chǔ)秒旋。之所為將chunk size定為64MB,主要有以下考慮:
1诀拭、可以減少client訪問master查詢meta信息的次數(shù)迁筛,降低master的訪問壓力。因?yàn)閏hunk size設(shè)計(jì)比較大耕挨,順序訪問一個(gè)超大文件時(shí)因?yàn)閏hunk數(shù)較少且client緩存了chunk meta信息细卧,所以訪問master的次數(shù)就會(huì)降低。甚至筒占,client可以緩存所有文件的chunk的meta信息贪庙,就算是隨機(jī)讀文件,master也不會(huì)成為系統(tǒng)性能瓶頸翰苫。
2止邮、可以減少網(wǎng)絡(luò)開銷,保持client與chunkserver的TCP連接奏窑,可以執(zhí)行更多的chunk操作导披。
3、可以減少master上需要在內(nèi)存中記錄的meta data數(shù)據(jù)量良哲,降低master的內(nèi)存占用盛卡。
?? size大的缺點(diǎn)是:小文件包含很少的chunk助隧,甚至只有一個(gè)筑凫。這樣的話,在多個(gè)client高并發(fā)查詢該小文件時(shí)對應(yīng)的chunk會(huì)成為熱點(diǎn)并村。實(shí)際上巍实,這種情況在GFS系統(tǒng)中很少發(fā)生,因?yàn)榇蟛糠謈lient的操作都是順序讀大文件哩牍。但是棚潦,考慮以下場景,我們部署一個(gè)服務(wù)的二進(jìn)制文件到GFS系統(tǒng)中膝昆,然后數(shù)百臺(tái)的服務(wù)器同時(shí)查詢二進(jìn)制文件并啟動(dòng)服務(wù)丸边,此時(shí)該二進(jìn)制文件副本所在的chunkserver立馬就會(huì)成為查詢瓶頸叠必。當(dāng)然,可以通過增加副本數(shù)和分散服務(wù)器的查詢時(shí)間來解決這種場景下的問題妹窖。
四纬朝、Metadata
??master主要存儲(chǔ)三種類型的metadata:file和chunk的名字空間,file到chunk的mapping信息以及chunk的副本分布骄呼。所有的metadata都在master的內(nèi)存中存儲(chǔ)共苛。前兩種meta信息可以持久化存儲(chǔ),將操作日志存儲(chǔ)在master的本地磁盤以及將備份日志存儲(chǔ)在遠(yuǎn)端機(jī)器上蜓萄。master不持久化存儲(chǔ)chunk的副本分布信息隅茎,而是通過與chunkserver交互來獲取chunkserver上的chunk信息。
4.1 in-memory data structure
??meta信息在內(nèi)存中嫉沽,所有master的操作很快辟犀。另外,master可以高效地定期在后臺(tái)scan所有的meta數(shù)據(jù)耻蛇,來執(zhí)行垃圾回收踪蹬、副本修復(fù)、均衡等臣咖。metadata都記錄在內(nèi)存中跃捣,所以GFS系統(tǒng)會(huì)比較關(guān)注chunk的數(shù)量以及master的可用內(nèi)存量。但是在實(shí)際場景下夺蛇,這不是問題疚漆。每個(gè)64MB的chunk的metadata小于64字節(jié),大部分的chunk都是滿負(fù)荷存儲(chǔ)的刁赦,除了文件最后一個(gè)chunk的空間是沒有完全被占用娶聘。由于文件的名字空間采用了前綴壓縮的方式存儲(chǔ),單個(gè)文件的meta信息也是小于64字節(jié)甚脉。如果需要擴(kuò)大系統(tǒng)規(guī)模的話丸升,可以很簡單地通過增大master的內(nèi)存就可以了。相比于系統(tǒng)的高可靠牺氨、高性能和簡潔性狡耻,增加內(nèi)存是很最小的代價(jià)了。
4.2 chunk 分布
??并沒有持久化存儲(chǔ)chunk的副本分布信息猴凹,而是在master啟動(dòng)時(shí)向chunkserver查詢其chunk信息夷狰,然后通過heartbeat來持續(xù)更新master的副本分布信息,以與chunkserver數(shù)據(jù)保持一致郊霎。GFS起初設(shè)計(jì)時(shí)嘗試將chunk的分布信息持久化存儲(chǔ)在master端沼头,隨后發(fā)現(xiàn)通過master啟動(dòng)時(shí)拉取然后通過heartbeat同步chunk信息的方式更簡單。因?yàn)椋?dāng)chunkserver加入进倍、退出土至、名字改變、重啟等行為經(jīng)常發(fā)生猾昆,這會(huì)導(dǎo)致維護(hù)master的chunk meta數(shù)據(jù)的正確性是非常困難的毙籽。從另一個(gè)角度考慮就是,只有chunkserver匯報(bào)的chunk信息才是集群中最真實(shí)的chunk分布毡庆,因?yàn)閙aster不需要自己維護(hù)一個(gè)chunk分布狀態(tài)坑赡,只需要以chunkserver的狀態(tài)匯報(bào)為準(zhǔn)即可。
4.3 操作日志
??日志記錄了GFS集群數(shù)據(jù)更改的歷史記錄么抗。操作日志對GFS來說是至關(guān)重要的毅否,因?yàn)樗粌H是metadata的持久化記錄,還記錄了并發(fā)操作的時(shí)序蝇刀。因?yàn)椴僮魅罩竞苤匾樱员仨毧煽康卮鎯?chǔ)。在metadata的change沒有持久化之前吞琐,client是不能看到的數(shù)據(jù)的更改捆探。當(dāng)client修改數(shù)據(jù)時(shí),操作記錄需要保存在多個(gè)遠(yuǎn)端機(jī)器上站粟,而且只有當(dāng)操作記錄持久化存儲(chǔ)在本地和遠(yuǎn)端以后黍图,才會(huì)回復(fù)client數(shù)據(jù)更改成功。
??可以通過回放操作日志來恢復(fù)文件系統(tǒng)奴烙。為了減少系統(tǒng)啟動(dòng)時(shí)replay的時(shí)間助被,必須縮減回放的日志量。master可以定期存儲(chǔ)metadata的checkpoint切诀,master重啟時(shí)可以從checkpoint加載metadata揩环,然后回放checkpoint之后的少量日志即可。
五幅虑、租約和數(shù)據(jù)更改
??數(shù)據(jù)更改主要指chunk的write或者append操作丰滑。數(shù)據(jù)的修改會(huì)在chunk的所有副本上執(zhí)行,GFS使用lease機(jī)制來保證chunk副本上修改操作的執(zhí)行順序倒庵。master將lease頒發(fā)給chunk的一個(gè)副本褒墨,稱之為primary,primary然后選擇chunk上其他副本的修改執(zhí)行順序哄芜。大概的執(zhí)行邏輯如下:1貌亭、client向master查詢chunk的primary所在的chunkserver以及其他副本的分布柬唯,如果沒有primary的花认臊,master會(huì)選擇一個(gè)作為該chunk的primary
2、master回復(fù)client primary和其他副本的分布信息锄奢。client會(huì)cache返回的metadata
3失晴、client將數(shù)據(jù)發(fā)送所有的副本剧腻。client可以以任意順序執(zhí)行。每個(gè)chunkserser都會(huì)在內(nèi)存的LRUbuffer中記錄數(shù)據(jù)涂屁。
4书在、當(dāng)所有的副本都返回已經(jīng)接收數(shù)據(jù)成功后,client會(huì)向primary發(fā)送一個(gè)寫請求拆又。primary會(huì)為每一個(gè)數(shù)據(jù)更改的請求附加一個(gè)序列號(hào)儒旬,數(shù)據(jù)更改是按照序列號(hào)的順序執(zhí)行的。
5帖族、primary將數(shù)據(jù)更改同步到其他副本中栈源,副本也是按照序列號(hào)執(zhí)行數(shù)據(jù)更改操作。
6竖般、primary接收到其他副本回復(fù)的數(shù)據(jù)操作完成
7甚垦、primary返回client結(jié)果。期間發(fā)生的所有錯(cuò)誤都會(huì)報(bào)給client涣雕。
六艰亮、副本分布
?? GFS集群一般都會(huì)有上百臺(tái)的chunkserver,分布在多個(gè)機(jī)架上挣郭。chunkserver也會(huì)接收來自本機(jī)架或者其他機(jī)架的上百個(gè)client的查詢請求迄埃。不同機(jī)架的服務(wù)器通信可能會(huì)途徑一個(gè)或者多個(gè)交換機(jī)轉(zhuǎn)發(fā)。chunk的副本分布選擇策略主要目的是盡量提高數(shù)據(jù)的可靠性和可用性兑障,同時(shí)最大化地充分利用網(wǎng)絡(luò)帶寬调俘。所以,僅僅將副本跨機(jī)器部署是不夠的旺垒。GFS將副本是跨機(jī)架部署的彩库,這樣可以保證在一個(gè)機(jī)架被損壞或者下線時(shí),chunk至少會(huì)有副本是可用的先蒋。
?? chunk的副本在下列情況下會(huì)被創(chuàng)建:創(chuàng)建chunk骇钦、副本修復(fù)、rebalance竞漾。當(dāng)master創(chuàng)建chunk時(shí)眯搭,會(huì)選擇存儲(chǔ)該chunk副本的chunkserver。主要考慮以下幾點(diǎn):
1业岁、新副本所在chunkserver的磁盤利用率低于系統(tǒng)的平均水平
2鳞仙、限制每個(gè)chunkserver最近一段時(shí)間創(chuàng)建chunk的數(shù)量
3、每個(gè)chunk的所有副本不能都在一個(gè)機(jī)架
?? chunk的副本數(shù)少于一定數(shù)量是笔时,master會(huì)復(fù)制一個(gè)副本棍好。這可能發(fā)生在chunkserver宕機(jī)或者chunkserver匯報(bào)自己的副本損壞或者chunkserver所在機(jī)器的磁盤損壞等等。每個(gè)chunk 復(fù)制任務(wù)都有優(yōu)先級(jí),按照優(yōu)先級(jí)由高到低子master中排隊(duì)等待執(zhí)行借笙。master還會(huì)定期掃描當(dāng)前副本的分布情況扒怖,一旦發(fā)現(xiàn)磁盤使用量或者機(jī)器負(fù)載不均衡,就會(huì)發(fā)起負(fù)載均衡操作业稼。無論是chunk創(chuàng)建盗痒、chunk復(fù)制還是負(fù)載均衡,選擇chunk副本的位置的策略都是相同的低散,并且需要限制副本修復(fù)和均衡的速度俯邓,否則會(huì)影響系統(tǒng)的正常讀寫服務(wù)。
??Google的成功表明單master的設(shè)計(jì)師可行的熔号。這不僅簡化了系統(tǒng)看成,而且能夠較好地實(shí)現(xiàn)一致性,給予性能考慮跨嘉,GFS提出了“記錄至少原子性追加一次”的一致性模型川慌。通過租約的方式將每個(gè)chunk的修改授權(quán)到chunkserver從而減少了master的負(fù)載,通過流水線的方式復(fù)制多個(gè)副本以減少延時(shí)祠乃。master維護(hù)的元數(shù)據(jù)很多梦重,需要設(shè)計(jì)高效的數(shù)據(jù)結(jié)構(gòu),且要保證占用內(nèi)存小和支持快照操作亮瓷。支持COW的B樹可以滿足需求琴拧,但是實(shí)現(xiàn)確實(shí)相當(dāng)復(fù)雜。