天天看點

GFS論文整理(四)

Data Integrity(資料完整性):

    每個chunkserver使用checksumming(校驗和)來檢測存儲資料的損壞.GFS分布式環境往往有數百台機器數千個硬碟,磁盤故障是一個很普通的事情,這往往會導緻在讀取或者寫入時資料的存壞或者丢失.我們能夠從其他chunk replicas中恢複這些損壞的資料.但是如果通過跨chunkserver的方式去檢測這些損壞的資料,是不現實的.此外,副本資料有些出入或許是正常的:GFS mutation的語義,特别是上述讨論過的原子record append,并不保證replicas完全一緻(逐位元組).是以,每個chunkserver必須獨自來校驗自己的副本的資料完整性,使用checksum.

    一個chunk(資料塊檔案)被拆分成64KB的block,每個block都有一個相應的32位checksum.像其他metadata一樣,checksums被儲存在記憶體中,通過日志持久存儲,和使用者實際資料隔離.

    對于reads,chunkserver在傳回任何資料給請求者(可能是client,也可能是其他chunkserver)之前,會使用checksum校驗讀取資料所在block,是以chunkserver不會把異常資料傳遞給其他機器(client或者其他chunkserver).如果block和記錄的checksum不比對,chunkserver将會傳回一個錯誤給client,并且會把這個不比對資訊報告master.收到響應後,請求者(client or other chunkserver)将會從其他的replicas讀取,同時master也會從其他chunk replicas複制這個chunk(有可能在其他chunkserver上clone,而非一定在出錯的replicas機器上複制).當一個有效的replicas被替換,master會訓示chunkserver删除這個mismatch的replicas.

    Checksumming有多方面的原因會對read性能有些影響,因為我們的read會分布在多個blocks上,我們需要額外的讀取一些相對較小的資料進行校驗.Client code通過對齊block邊界來更進一步降低開支.此外,checksum查找和比較無需任何IO,并且checksum的計算經常和其他I/O操作同時進行.

    Checksum計算做了較大的優化,針對chunk尾部追加的write(而不是覆寫現有資料的write),因為它們(append write)占據了我們了工作量.我們之需要增量的更新最後一個block部分的checksum,(增加block或者block内容變更才會導緻checksum的生成和計算),為append操作填充資料的block計算出一個新的checksum.即使最後一個checksum block已經損壞了,我們現在無法檢測它,這個新的checksum值不會比對現存的資料,這個損壞的資料将會在下一次block被讀取時才會校驗.

    相反,如果write是覆寫(overwrite)現有的chunk區間,我們必須讀取然後校驗覆寫區間内第一個和最後一個block,然後執行write,最後計算和記錄這個新的checksums.如果我們在覆寫資料之前,不去校驗第一個和最後一個blocks,那麼新的checksums可能會隐藏沒有被覆寫區域的損壞的資料.

    在空閑時期,chunservers能夠掃描和校驗那寫不活躍的chunks的内容.這就允許我們檢測chunks中損壞資料,在它讀取操作較少的時候.一旦發現損壞資料,master能就會建立一個沒有損壞資料的replicas和删除損壞資料的replicas(通過複制),以防止這些非活躍但是損壞的chunk replicas愚弄master認為它有足夠多有效的replicas.

GFS論文整理(四)

Diagnostic Tools(故障診斷工具):

    詳細的診斷日志對發現問題/調試/性能分析有一定的幫助,它之需要較小的開支.沒有日志,對于了解偶然的/不能重制的機器件互動,是很困難.GFS伺服器産生診斷日志,記錄了許多重要的事件(例如chunkserver的上下線)和所有的RPC請求和響應.這些診斷日志能夠在不影響系統正确性前提下,随意的删除.不過,我們會盡量存儲這些日志隻要空間允許.

    PRC日志包括在網絡上傳輸的請求和響應細節,除去讀取或者寫入的檔案資料外.通過比對和比較不同機器上的PRC請求和響應,我們能夠重建整個互動曆史過程,以診斷問題.這個logs也能用來各種負載測試和性能分析.

    診斷日志的性能影響是微小的(相對收益而言),引文這些日志順序的寫入,而且是異步的.最近的一些事件儲存在記憶體中,可以持續的線上監控.

Measurements:

    這在一章節,我們主要展示幾個micro-benchmarks來描述GFS架構和實作上的瓶頸.還有一些來自google實際的分布式的資料.

    Micro-benchmarks:

    我們測量GFS分布式環境的性能:一個master,2個master replicas,16個chunkservers,16個clients.注意這個配置設定是用來測試,通常分布式具有數百個chunkserver和clients.所有的機器都是1.4G雙核處理器,2GB記憶體,2個80 5400rpm硬碟,100M全雙工網卡,連結到HP 2524交換機上.全部19台server機器連結到一個交換機上,16個client機器連結到另外一個交換機.這2個交換機之間通過1Gbps鍊路連結.

    Read:

    N個client同時從檔案系統中讀取.每個client從320GB的集合中,讀取随即選取的4MB 區域.重複256次,最終每個client讀取了1GB資料.chunkserver總共隻有32GB記憶體,是以我們期望10%的命中率在linux buffer cache中.

    圖3展示了N個用戶端整體的讀取速率,以及理論上限。整體的上限在2個交換機直接1GB鍊路上,為125M/S,或者用戶端在100M網卡飽和的情況下為12.5M/s(平均每個用戶端)。當隻有一個用戶端讀取時,觀測到其讀取速率為10M/s,為每個用戶端上限的80%。16個用戶端整體的讀取速率可達94M/s,為125M上限的75%。由80%降低到75%,是由于reader的個數增加,是以可能是多個readers同時從同一個chunkservers讀取資料造成。

    Writes:

    N個client同時向N個不同的files中進行寫操作,每個client以1M為寫入單元,共向一個新檔案中寫入1GB的資料。其總體寫入速率和它的理論上限如圖。理論上限為64M/s,因為我們需要把每個位元組寫入到16個中3個chunkservers上,每個都有12.5M的輸傳入連結接。每個client的寫入速率為6.3M/s,大約為寫入上限的一半,主要原因是我們的網絡協定棧。它與我們push data 到chunk replicas所使用的流水線模式(pipleline),不能很好的互動。replicas直接傳播資料的延遲,降低了整體的寫入速率。寫入操作比預期的要慢,事實上,這不是一個主要的問題,即使某個client的延遲增加,在大量client的情況下,也将不會太大的影響整體的寫入帶寬。

    Record appends:

    圖三展示了record append的性能,N個clients同時向一個檔案append資料.性能受到了存儲最後一個chunk檔案的chunkserver的帶寬的限制,和用戶端的數量沒有關系.單個用戶端6.0M/S,在16個用戶端是降低到4.8M/S,主要歸因與網絡阻塞和傳輸速度的不同.

    我們的應用多數情況下是并發的生成多個這樣的檔案.換句話說,N個clients向M個共享的檔案中同時append,N和M都是上百的數字.是以,chunkserver的網絡阻塞在實踐中不是一個嚴重的問題.

Experiences(經驗):

    在建構和部署GFS過程中,我們經曆了一些問題,一些操作和技術上的.

    起初,GFS被設想為一個為生産系統服務的背景檔案系統.随着時間遷移,它發展為包括研究和研發的任務.開始時極少的功能支援例如權限和配額,但是現在全面支援了這些.當生産系統是嚴格控制的,但是使用者曾有時不是如此.需要更多的基礎設定(功能)來保持使用者之間的隔離(互相幹擾).

    我們一些最大的問題就是硬碟和linux相關的.許多硬碟生成它們支援IDE協定的一定的版本範圍的linux驅動,但是實際上它們隻支援最新的(驅動版本).盡管這些協定版本比較接近,驅動也能工作,但是偶爾的不比對會導緻驅動和核心disagree about the drive's state.這會導緻核心悄無聲息的丢失資料.這個問題會促使我們使用checksum來檢測資料的損壞,同時我們也修改核心來處理這種協定上的不比對.

    早期我們出現過一些問題,在linux2.2核心上,fsync()的性能開支.它的開支與檔案的大小而不是被修改部分的大小有關.對于我們的大尺寸operation log特别是在實作checkpoiting之前是一個問題.我們在這個問題上徘徊了很久,最後遷移到了linux2.4.

    另外一個linux問題是單一reader-writer鎖,某個位址空間的線程從disk載入(reader lock,磁盤IO)或者在mmap()調用修改位址空間時,它(線程)必須先hold一個reader-writer lock.我們發現在系統負載很低的時候,也有逾時情況出現.我們費勁周折來查找系統平靜和硬體問題.最終,我們發現這個single lock,在磁盤線程交換以前的映射資料到磁盤時,會阻塞primary network線程映射新的資料到記憶體.因為我們主要受限與網絡接口,而不是記憶體複制的帶寬(難以了解,什麼意思???),我們使用pread()替換mmap(),用額外的copy解決這個問題.

    雖然偶爾的問題,linux代碼還是幫助了我們了解探索和了解系統的行為.在合适的時機,我們會改進核心和共享我們的這些改動給開源組織.

Related work(相關工作):

    和其他大型分布式檔案系統一樣,GFS提供了一個與位置無關的namespace,它能夠讓資料根據負載均衡或者容錯的需要,透明的遷移.因為磁盤是相對的便宜以及replication比傳統的RAID(陣列)方式簡單.GFS目前隻使用了replication方式進行資料備援.

CONCLUSION:GFS展示了使用普通的商用硬體提供了大規模資料處理的能力.

GFS論文整理(一):[http://shift-alt-ctrl.iteye.com/blog/1842245]

GFS論文整理(二):[http://shift-alt-ctrl.iteye.com/blog/1842286]

GFS論文整理(三):[http://shift-alt-ctrl.iteye.com/blog/1842509]

繼續閱讀