簡單總結(jié)一下,以GlusterFS為代表的無中心設(shè)計(jì)帶來的一些問題如下圖所示。 

有中心的存儲(chǔ)設(shè)計(jì):Hadoop

Hadoop的設(shè)計(jì)目標(biāo)是存大文件、做offline分析、可伸縮性好。Hadoop的元數(shù)據(jù)存儲(chǔ)節(jié)點(diǎn)(NameNode節(jié)點(diǎn))屬于主從式存儲(chǔ)模式,盡量將數(shù)據(jù)加載到內(nèi)存,能提高對數(shù)據(jù)的訪問性能。另外,放棄高可用,可進(jìn)一步提高元數(shù)據(jù)的響應(yīng)性能(NameNode的變更不是同步更新到從機(jī),而是通過定期合并的方式來更新)。

Hadoop具有以下幾方面優(yōu)點(diǎn):

  1. 為大文件服務(wù)。例如在塊大小為64MB時(shí),10PB文件只需要存儲(chǔ)1.6億條數(shù)據(jù),如果每條200Byte,那么需要32GB左右的內(nèi)存。而元信息的QPS也不用太高,如果每次QPS能提供一個(gè)文件塊的讀寫,那么1000QPS就能達(dá)到512Gb/s的讀寫速度,滿足絕大部分?jǐn)?shù)據(jù)中心的需求。
  2. 為offline業(yè)務(wù)服務(wù)。高可用服務(wù)可以部分犧牲。
  3. 為可伸縮性服務(wù)??梢陨炜s存儲(chǔ)節(jié)點(diǎn),元信息節(jié)點(diǎn)無需伸縮。

然而有如此設(shè)計(jì)優(yōu)點(diǎn)的Hadoop為什么不適合在公有云領(lǐng)域提供服務(wù)呢?

  1. 元信息容量太小。在公有云平臺(tái)上,1.6億是個(gè)非常小的數(shù)字,單個(gè)熱門互聯(lián)網(wǎng)應(yīng)用的數(shù)據(jù)都不止這些。1.6億條數(shù)據(jù)占用32GB內(nèi)存,100億條數(shù)據(jù)需要2000GB內(nèi)存,這時(shí)Hadoop就完全扛不住了。
  2. 元信息節(jié)點(diǎn)無法伸縮。元信息限制在單臺(tái)服務(wù)器,1000QPS甚至是優(yōu)化后的15000QPS的單機(jī)容量遠(yuǎn)不能達(dá)到公有云的需求。
  3. 高可用不完美。就是前面所提到的NameNode問題,在業(yè)務(wù)量太大時(shí),Hadoop支撐不住。

因此,做有中心的云存儲(chǔ)時(shí),通常的做法是完全拋棄掉原先的單中心節(jié)點(diǎn)設(shè)計(jì),引入一些其他的設(shè)計(jì)。

常見的是WRN算法,為數(shù)據(jù)準(zhǔn)備多個(gè)樣本,寫入W份才成功,成功讀取R份才算成功,W+R大于N(其中N為總副本數(shù))。這樣就解決了之前提到的高可用問題,任何一個(gè)副本宕機(jī),整個(gè)系統(tǒng)的讀寫都完全不受影響。

在這個(gè)系統(tǒng)里,利用這種技術(shù)有以下幾個(gè)問題需要注意:

  1. W,R,N選多少合適。第一種選擇2,2,3,一共三副本,寫入兩份成功,讀取時(shí)成功讀取兩份算成功。但是其中一臺(tái)機(jī)器下線的話,會(huì)出現(xiàn)數(shù)據(jù)讀不出來的情況,導(dǎo)致數(shù)據(jù)不可用。第二種選擇4,4,6或者6,6,9,能夠容忍單機(jī)故障。但機(jī)器越多,平均響應(yīng)時(shí)間越長。
  2. 失敗的寫入會(huì)污染數(shù)據(jù)。比如4,4,6的場景,如果寫入只成功了3份,那么這次寫入是失敗的。但如果寫入是覆蓋原來的元數(shù)據(jù),就意味著現(xiàn)在有三份正確的數(shù)據(jù),有三份錯(cuò)誤的數(shù)據(jù),無法判斷哪份數(shù)據(jù)正確,哪份數(shù)據(jù)錯(cuò)誤?;乇艿姆椒ㄊ菍懭霐?shù)據(jù)帶版本(不覆蓋,只是追加),即往數(shù)據(jù)庫里面插入新數(shù)據(jù)。有些云存儲(chǔ)的使用方法是對一個(gè)文件進(jìn)行反復(fù)的修改,比如用M3U8文件直播。隨著直播進(jìn)程的開始不停地更改文件,大概5秒鐘一次,持續(xù)一個(gè)小時(shí)文件會(huì)被修改720次。這時(shí)候從數(shù)據(jù)庫讀取文件信息時(shí),就不再是讀1條記錄,而是每臺(tái)讀取720條記錄,很容易導(dǎo)致數(shù)據(jù)庫出現(xiàn)性能瓶頸。

下面,我們簡單總結(jié)一下以Hadoop為代表的有中心的存儲(chǔ)設(shè)計(jì)速存在的問題:

基于數(shù)據(jù)庫的分布式存儲(chǔ)設(shè)計(jì):GridFS和HBase

GridFS

GridFS基于MongoDB,相當(dāng)于一個(gè)文件存儲(chǔ)系統(tǒng),是一種分塊存儲(chǔ)形式,每塊大小為255KB。數(shù)據(jù)存放在兩個(gè)表里,一個(gè)表是chunks,加上元信息后單條記錄在256KB以內(nèi);另一個(gè)表是files,存儲(chǔ)文件元信息。

GridFS的優(yōu)點(diǎn)如下所述。

  1. 可以一次性滿足數(shù)據(jù)庫和文件都需要持久化這兩個(gè)需求。絕大部分應(yīng)用的數(shù)據(jù)庫數(shù)據(jù)需要持久化,用戶上傳的圖片也要做持久化,GridFS用一套設(shè)施就能滿足,可以降低整個(gè)運(yùn)維成本和機(jī)器采購成本。
  2. 擁有MongoDB的全部優(yōu)點(diǎn):在線存儲(chǔ)、高可用、可伸縮、跨機(jī)房備份。
  3. 支持Range GET,刪除時(shí)可以釋放空間(需要用MongoDB的定期維護(hù)來釋放空間)。

GridFS的缺點(diǎn)如下所述:

  1. oplog耗盡。oplog是MongoDB上一個(gè)固定大小的表,用于記錄MongoDB上的每一步操作,MongoDB的ReplicaSet的同步依賴于oplog。一般情況下oplog在5GB~50GB附近,足夠支撐24小時(shí)的數(shù)據(jù)庫修改操作。但如果用于GridFS,幾個(gè)大文件的寫入就會(huì)導(dǎo)致oplog迅速耗盡,很容易引發(fā)secondary機(jī)器沒有跟上,需要手工修復(fù),大家都知道,MongoDB的修復(fù)非常費(fèi)時(shí)費(fèi)力。簡單來說,就是防沖擊能力差,跟數(shù)據(jù)庫的設(shè)計(jì)思路有關(guān),畢竟不是為文件存儲(chǔ)設(shè)計(jì)的。除了手工修復(fù)的問題,沖擊還會(huì)造成主從數(shù)據(jù)庫差異拉大,對于讀寫分離,或者雙寫后再返回等使用場景帶來不小的挑戰(zhàn)。
  2. 濫用內(nèi)存。MongoDB使用MMAP將磁盤文件映射到內(nèi)存。對于GridFS來說,大部分場景都是文件只需讀寫一次,對這種場景沒法做優(yōu)化,內(nèi)存浪費(fèi)巨大,會(huì)擠出那些需要正常使用內(nèi)存的數(shù)據(jù)(比如索引)。這也是設(shè)計(jì)阻抗失配帶來的問題。
  3. 伸縮性問題。需要伸縮性就必須引入MongoDB Sharding,需要用files_id作Sharding,如果不修改程序,files_id遞增,所有的寫入都會(huì)壓入最后一組節(jié)點(diǎn),而不是均勻分散。在這種情況下,需要改寫驅(qū)動(dòng),引入一個(gè)新的files_id生成方法。另外,MongoDBSharding在高容量壓力下的運(yùn)維很痛苦。MongoDB Sharding需要分裂,分裂的時(shí)候響應(yīng)很差,會(huì)導(dǎo)致整個(gè)服務(wù)陷入不可用的狀態(tài)。

對GridFS的總結(jié)如下:

HBase

前面提到Hadoop因?yàn)镹ameNode容量問題,所以不適合用來做小文件存儲(chǔ),那么HBase是否合適呢?

HBase有以下優(yōu)點(diǎn):

  1. 伸縮性、高可用都在底層解決了。
  2. 容量很大,幾乎沒有上限。

但缺點(diǎn)才是最關(guān)鍵的,HBase有以下缺點(diǎn)。

  1. 微妙的可用性問題。首先是Hadoop NameNode的高可用問題。其次,HBase的數(shù)據(jù)放在Region上,Region會(huì)有分裂的問題,分裂和合并的過程中Region不可用,不管用戶這時(shí)是想讀數(shù)據(jù)還是寫數(shù)據(jù),都會(huì)失敗。雖然可以用預(yù)分裂回避這個(gè)問題,但這就要求預(yù)先知道整體規(guī)模,并且key的分布是近均勻的。在多用戶場景下,key均勻分布很難做到,除非舍棄掉key必須按順序這個(gè)需求。
  2. 大文件支持。HBase對10MB以上的大文件支持不好。改良方案是將數(shù)據(jù)拼接成大文件,然后HBase只存儲(chǔ)文件名、offset和size。這個(gè)改良方案比較實(shí)用,但在空間回收上需要補(bǔ)很多開發(fā)的工作。

應(yīng)對方案是HBase存元數(shù)據(jù),Hadoop存數(shù)據(jù)。但是,Hadoop是為offline設(shè)計(jì)的,對NameNode的高可用考慮不充分。HBase的Region分拆和合并會(huì)造成短暫的不可用,如果可以,最好做預(yù)拆,但預(yù)拆也有問題。如果對可用性要求低,那么這種方案可用。

繞過問題的存儲(chǔ)設(shè)計(jì):FastDFS

Hadoop的問題是NameNode壓力過高,那么FastDFS的思路是給NameNode減壓。減壓方法是將NameNode的信息編碼到key中。對于范例URL:group1/M00/00/00/rBAXr1AJGF_3rCZAAAAEc45MdM850_big.txt來說,NameNode只需要做一件事,將group1翻譯成具體的機(jī)器名字,不用關(guān)心key的位置,只要關(guān)心組的信息所在的位置,而這個(gè)組的信息就放在key里面,就繞過了之前的問題。

FastDFS的優(yōu)點(diǎn)如下:

  1. 結(jié)構(gòu)簡單,元數(shù)據(jù)節(jié)點(diǎn)壓力低。
  2. 擴(kuò)容簡單,擴(kuò)容后無需重新平衡。

FastDFS的缺點(diǎn)如下:

  1. 不能自定義key,這對多租戶是致命的打擊,自己使用也會(huì)降低靈活性。
  2. 修復(fù)速度:磁盤鏡像分布,修復(fù)速度取決于磁盤寫入速度,比如4TB的盤,100MB/s的寫入速度,至少需要11個(gè)小時(shí)。
  3. 大文件沖擊問題沒有解決。首先,文件大小有限制(不能超過磁盤大?。?;其次,大文件沒有分片,導(dǎo)致大文件的讀寫都由單塊盤承擔(dān),所以對磁盤的網(wǎng)絡(luò)沖擊很大。

結(jié)語

本文基于七牛首席架構(gòu)師李道兵在QCon會(huì)議上的演講內(nèi)容整理而成,著重對幾種存儲(chǔ)設(shè)計(jì)進(jìn)行了比較全面的分析,總結(jié)如下。而關(guān)于分布式存儲(chǔ)的元數(shù)據(jù)設(shè)計(jì)還有很多更為細(xì)節(jié)的點(diǎn)和經(jīng)驗(yàn)值得探討,留待日后慢慢與大家交流。

分享到

fanz

相關(guān)推薦