|
存儲系統(tǒng)從其與生俱來的使命來說,就難以擺脫復雜系統(tǒng)的魔咒。無論是從單機時代的文件系統(tǒng),還是后來C/S或B/S結(jié)構(gòu)下數(shù)據(jù)庫這樣的存儲中間件興起,還是如今炙手可熱的云存儲服務來說,存儲都很復雜,而且是越來越復雜。
存儲為什么會復雜,要從什么是存儲談起。存儲這個詞非常平凡,存儲 + 計算(操作)就構(gòu)成了一個樸素的計算機模型。簡單來說,存儲就是負責維持計算系統(tǒng)的狀態(tài)的單元。從維持狀態(tài)的角度,我們會有最樸素的可靠性要求。比如單機時代的文件系統(tǒng),機器斷電、程序故障、系統(tǒng)重啟等常規(guī)的異常,文件系統(tǒng)必須可以正確地應對,甚至對于磁盤扇區(qū)損壞,文件系統(tǒng)也需要考慮盡量將損失降到最低。對于大部分的業(yè)務程序而言,你只需要重點關注業(yè)務的正常分支流程就行,對于出乎意料的情況,通常只需拋出一個錯誤,告訴用戶你不該這么玩。但是對于存儲系統(tǒng),你需要花費絕大部分精力在各種異常情況的處理上,甚至你應該認為,這些龐雜的、多樣的錯誤分支處理,才是存儲系統(tǒng)的“正常業(yè)務邏輯”。
到了互聯(lián)網(wǎng)時代,有了C/S或B/S結(jié)構(gòu),存儲系統(tǒng)又有了新指標:可用性。為了保證服務質(zhì)量,那些用戶看不見的服務器程序必須時時保持在線,最好做到邏輯上是不宕機的(可用性100%)。服務器程序怎么才能做到高可用性?答案是存儲中間件。沒有存儲中間件,意味著所有的業(yè)務程序,都必須考慮每做一步就對狀態(tài)進行持久化,以便自己掛掉后另一臺服務器(或者自己重啟后),知道之前工作到哪里了,接下去應該做些什么。但是對狀態(tài)進行持久化(也就是存儲)會非常繁瑣,如果每個業(yè)務都自己實現(xiàn),負擔無疑非常沉重。但如果有了高可用的存儲中間件,服務器端的業(yè)務程序就只需操作存儲中間件來更新狀態(tài),通過同時啟動多份業(yè)務程序的實例做互備和負載均衡,很容易實現(xiàn)業(yè)務邏輯上不宕機。
所以,數(shù)據(jù)庫這樣的存儲中間件出現(xiàn)基本上是歷史必然。盡管數(shù)據(jù)庫很通用,但它決不會是唯一的存儲中間件。比如業(yè)務中用到的富媒體(圖片、音視頻、Office文檔等),我們很少會去存儲到數(shù)據(jù)庫中,更多的時候我們會把它們放在文件系統(tǒng)里。但是單機時代誕生的文件系統(tǒng),真的是最適合存儲這些富媒體數(shù)據(jù)的么?不,文件系統(tǒng)需要改變,因為:
- 伸縮性。單機文件系統(tǒng)的第一個問題是單機容量有限,在存儲規(guī)模超過一臺機器可管理的時候,應該怎么辦。
- 性能瓶頸。通常,單機文件系統(tǒng)在文件數(shù)目達到臨界點后,性能會快速下降。在4TB的大容量磁盤越來越普及的今天,這個臨界點相當容易到達。
- 可靠性要求。單機文件系統(tǒng)通常只是單副本的方案,但是今天單副本的存儲早已無法滿足業(yè)務的可靠性要求。數(shù)據(jù)需要有冗余(比較經(jīng)典的做法是3副本),并且在磁盤損壞時及早修復丟失的數(shù)據(jù),以避免所有的副本損壞造成數(shù)據(jù)丟失。
- 可用性要求。單機文件系統(tǒng)通常只是單副本的方案,在該機器宕機后,數(shù)據(jù)就不可讀取,也不可寫入。
在分布式存儲系統(tǒng)出現(xiàn)前,有一些基于單機文件系統(tǒng)的改良版本被一些應用采納。比如在單機文件系統(tǒng)上加 RAID5 做數(shù)據(jù)冗余,來解決單機文件系統(tǒng)的可靠性問題。假設 RAID5 的數(shù)據(jù)修復時間是1天(實際上往往做不到,尤其是業(yè)務系統(tǒng)本身壓力比較大的情況下,留給 RAID 修復用的磁盤讀寫帶寬很有限),這種方案單機的可靠性大概是100年丟失一次數(shù)據(jù)(即可靠性是2個9)。看起來尚可?但是你得小心兩種情況。一種是你的集群規(guī)模變大,你仍然沿用這個土方法,比如你現(xiàn)在有 100 臺這樣的機器,那么就會變成1年就丟失一次數(shù)據(jù)。另一種情況是如果實際數(shù)據(jù)修復時間是 3 天,那么單機的可靠性就直降至4年丟失一次數(shù)據(jù),100臺就會是15天丟失一次數(shù)據(jù)。這個數(shù)字顯然無法讓人接受。
Google GFS 是很多人閱讀的第一份分布式存儲的論文,這篇論文奠定了 3 副本在分布式存儲系統(tǒng)里的地位。隨后 Hadoop 參考此論文實現(xiàn)了開源版的 GFS —— HDFS。但關于 Hadoop 的 HDFS 實際上業(yè)界有不少誤區(qū)。GFS 的設計有很強的業(yè)務背景特征,本身是用來做搜索引擎的。HDFS 更適合做日志存儲和日志分析(數(shù)據(jù)挖掘),而不是存儲海量的富媒體文件。因為:
- HDFS 的 block 大小為 64M,如果文件不足 64M 也會占用 64M。而富媒體文件大部分仍然很小,比如圖片常規(guī)尺寸在 100K 左右。有人可能會說我可以調(diào)小 block 的尺寸來適應,但這是不正確的做法,HDFS 的架構(gòu)是為大文件而設計的,不可能簡單通過調(diào)整 block 大小就可以滿足海量小文件存儲的需求。
- HDFS 是單 Master 結(jié)構(gòu),這決定了它能夠存儲的元數(shù)據(jù)條目數(shù)有限,伸縮性存在問題。當然作為大文件日志型存儲,這個瓶頸會非常晚才遇到;但是如果作為海量小文件的存儲,這個瓶頸很快就會碰上。
- HDFS 仍然沿用文件系統(tǒng)的 API 形式,比如它有目錄這樣的概念。在分布式系統(tǒng)中維護文件系統(tǒng)的目錄樹結(jié)構(gòu),會遭遇諸多難題。所以 HDFS 想把 Master 擴展為分布式的元數(shù)據(jù)集群并不容易。
分布式存儲最容易處理的問題域還是單鍵值的存儲,也就是所謂的 Key-Value 存儲。只有一個 Key,就意味著我們可以通過對 Key 做 Hash,或者對 Key 做分區(qū),都能夠讓請求快速定位到特定某一臺存儲機器上,從而轉(zhuǎn)化為單機問題。這也是為什么在數(shù)據(jù)庫之后,會冒出來那么多 NoSQL 數(shù)據(jù)庫。因為數(shù)據(jù)庫和文件系統(tǒng)一樣,最早都是單機的,在伸縮性、性能瓶頸(在單機數(shù)據(jù)量太大時)、可靠性、可用性上遇到了相同的麻煩。NoSQL 數(shù)據(jù)庫的名字其實并不恰當,他們更多的不是去 SQL,而是去關系(我們知道數(shù)據(jù)庫更完整的稱呼是關系型數(shù)據(jù)庫)。有關系意味著有多個索引,也就是有多個 Key,而這對數(shù)據(jù)庫轉(zhuǎn)為分布式存儲系統(tǒng)來說非常不利。
七牛云存儲的設計目標是針對海量小文件的存儲,所以它對文件系統(tǒng)的第一個改變也是去關系,也就是去目錄結(jié)構(gòu)(有目錄意味著有父子關系)。所以七牛云存儲不是文件系統(tǒng)(File System),而是鍵值存儲(Key-Value Storage),用時髦點的話說是對象存儲(Object Storage)。不過七牛自己喜歡把它叫做資源存儲(Resource Storage),因為它是用來存儲靜態(tài)資源文件的。蠻多七牛云存儲的新手會問,為什么我在七牛的 API 中找不到創(chuàng)建目錄這樣的 API,根本原因還是受文件系統(tǒng)這個經(jīng)典存儲系統(tǒng)的影響。
七牛云存儲的第一個實現(xiàn)版本,從技術上來說是經(jīng)典的 3 副本的鍵值存儲。它由元數(shù)據(jù)集群和數(shù)據(jù)塊集群組成。每個文件被切成了 4M 為單位的一個個數(shù)據(jù)塊,各個數(shù)據(jù)塊按 3 副本做冗余。但是作為云存儲,它并不僅僅是一個分布式存儲集群,它需要額外考慮:
- 網(wǎng)絡問題,也就是文件的上傳下載問題。文件上傳方面,我們得考慮在相對比較差的網(wǎng)絡條件下(比如2G/3G網(wǎng)絡)如何確保文件能夠上傳成功,大文件(七牛云存儲的單文件大小理論極限是1TB)如何能夠上傳成功,如何能夠更快上傳。文件下載加速方面,考慮到 CDN 已經(jīng)發(fā)展了 10 多年的歷史,非常成熟,我們決定基于 CDN 來做下載加速。
- 數(shù)據(jù)處理。當用戶文件托管到了七牛,那么針對文件內(nèi)容的數(shù)據(jù)處理需求也會自然衍生。比如我們第一個客戶就給我們提了圖片縮略圖相關的需求。在音視頻內(nèi)容越來越多的時候,自然就有了音視頻轉(zhuǎn)碼的需求。可以預見在Office文檔多了后,也就會有 Office 文檔轉(zhuǎn)換的需求。
所以從技術上來說,七牛云存儲是這樣的:
七牛云存儲 = 分布式存儲集群 + 上傳加速網(wǎng)絡(下載外包給CDN) + 數(shù)據(jù)處理集群
網(wǎng)絡問題并不是七牛要解決的核心問題,只是我們要面對的現(xiàn)實困難。所以在這個問題上如果能夠有足夠?qū)I(yè)的供應商,能夠外包我們會盡可能外包。而分布式存儲集群的演進和優(yōu)化,才是我們最核心的事情。早在 2012 年 2 月,我們就啟動了新一代基于糾刪碼算術冗余的存儲系統(tǒng)的研發(fā)。新存儲系統(tǒng)的關注焦點在:
- 成本。經(jīng)典的 3 副本存儲系統(tǒng)雖然經(jīng)典,但是代價也是高昂的,需要我們投入 3 倍的存儲成本。那么有沒有保證高可靠和高可用的前提下把成本做下來?
- 可靠性。如何進一步提升存儲系統(tǒng)的可靠性?答案是更高的容錯能力(從允許同時損壞2塊盤到允許同時損壞4塊盤),更快的修復速度(從原先3小時修復一塊壞盤到30分鐘修復一塊壞盤)。
- 伸縮性。如何從系統(tǒng)設計容量、IO吞吐能力、網(wǎng)絡拓撲結(jié)構(gòu)等角度,讓系統(tǒng)能夠支持EB級別的數(shù)據(jù)存儲規(guī)模?關于伸縮性這個話題,涉及的點是全方位的,本文不展開討論,后面我們另外獨立探討這個話題(讓我們把焦點放在成本和可靠性上)。
在經(jīng)過了四個大的版本迭代,七牛新一代云存儲(v2)終于上線。新存儲的第一大亮點是引入了糾刪碼(EC)這樣的算術冗余方案,而不再是經(jīng)典的 3 副本冗余方案。我們的 EC 采用的是 28 + 4,也就是把文件切分為 28 份,然后再根據(jù)這 28 份數(shù)據(jù)計算出 4 份冗余數(shù)據(jù),最后把這 32 份數(shù)據(jù)存儲在 32 臺不同的機器上。這樣做的好處是既便宜,又提升了可靠性和可用性。從成本角度,同樣是要存儲 1PB 的數(shù)據(jù),要買的存儲服務器只需 3 副本存儲的 36.5%,經(jīng)濟效益相當好。從可靠性方面,以前 3 副本只能允許同時損壞2塊盤,現(xiàn)在能夠允許同時損壞4塊盤,直觀來說這大大改善了可靠性(后面討論可靠性的時候我們給出具體的數(shù)據(jù))。從可用性角度,以前能夠接受 2 臺服務器下線,現(xiàn)在能夠同時允許 4 臺服務器下線。
新存儲的第二大亮點是修復速度,我們把單盤修復時間從 3 小時提升到了 30 分鐘以內(nèi)。修復時間同樣對提升可靠性有著重要意義(后面討論可靠性的時候我們給出具體的數(shù)據(jù))。這個原因是比較容易理解的。假設我們的存儲允許同時壞 M 塊盤而不丟失數(shù)據(jù),那么集群可靠性,就是看在單位修復時間內(nèi),同時損壞 M+1 塊盤的概率。例如,假設我們修復時間是 3 小時,那么 3 副本集群的可靠性就是看 3 小時內(nèi)同時損壞 3 塊盤的概率(也就是丟數(shù)據(jù)的概率)。
讓我們回到存儲系統(tǒng)最核心的指標 —— 可靠性。首先,可靠性和集群規(guī)模是相關的。假設我們有 1000 塊磁盤的集群,對于 3 副本存儲系統(tǒng)來說,這 1000 塊盤同時壞 3 塊就會發(fā)生數(shù)據(jù)丟失,這個概率顯然比 3 塊盤同時壞 3 塊要高很多。基于這一點,有些人會想這樣的土方法:那我要不把集群分為 3 塊磁盤一組互為鏡像,1000 塊盤就是 333 組(不好意思多了1塊,我們忽略這個細節(jié)),是不是可以提升可靠性?這些同學忽略了這樣一些關鍵點:
- 3 塊盤同時壞 3 塊盤(從而丟失數(shù)據(jù))的概率為 p,那么 333 組這樣的集群,丟失數(shù)據(jù)的概率是 1-(1-p)^333 ≈ p * 333,而不是 p。
- 互為鏡像的麻煩之處是修復速度存在瓶頸。壞一塊盤后你需要找一個新盤進行數(shù)據(jù)對拷,而一塊大容量磁盤數(shù)據(jù)對拷的典型時間是 15 小時(我們后面將給出 15 小時同時壞 3 塊盤的概率)。要想提升這個修復速度,第一步我們就需要打破鏡像帶來的束縛。
如果一個存儲系統(tǒng)的修復時間是恒定的,那么這個存儲集群在規(guī)模擴大的時候,必然伴隨著可靠性的降低。所以最理想的情況是集群越大,修復速度越快。這樣才能抵消因集群增大導致壞盤概率增加帶來負面影響。計算表明,如果我們修復速度和集群規(guī)模成正比(線性關系),那么集群隨著規(guī)模增大,可靠性會越來越高。
下表列出了1000塊硬盤的存儲集群在不同存儲方案、不同修復時間下的可靠性計算結(jié)果:
副本存儲方案 | 容錯度(M) | 修復時間 | 數(shù)據(jù)丟失概率(P) | 可靠性 |
3副本方案 | 2 | 30分鐘 | 1. 00E-08 | 8個9 |
3小時 | 1. 00E-05 | 5個9 | ||
15小時 | 1. 00E-02 | 2個9 | ||
28+4算術冗余方案 | 4 | 30分鐘 | 1. 00E-16 | 16個9 |
3小時 | 1. 00E-11 | 11個9 | ||
15小時 | 1. 00E-07 | 7個9 |
對于數(shù)據(jù)丟失概率具體的計算公式和計算方法,由于篇幅所限,本文中不做展開,我會另找機會討論。
對我個人而言,七牛新一代云存儲(v2)的完成,了了我多年的夙愿。但七牛不會就此停止腳步。我們在存儲系統(tǒng)上又有了一些好玩的想法。從長遠來說,單位存儲的成本會越來越廉價(硬件和軟件系統(tǒng)都會推動這個發(fā)展趨勢)。而存儲系統(tǒng)肯定會越來越復雜。例如,有賴于超高的容錯能力,七牛對單塊磁盤的可靠性要求降低了很多,這就為未來我們采用桌面硬盤而不是企業(yè)硬盤作為存儲介質(zhì)打下基礎。但是單塊磁盤可靠性的降低,則會進一步推動存儲系統(tǒng)往復雜的方向發(fā)展。基于這個推理,我認為存儲必然需要轉(zhuǎn)為云服務,成為水電煤一樣的基礎設施。存儲系統(tǒng)越來越復雜,越來越專業(yè),這就導致自建存儲的難度和成本越來越高,自建存儲的必要性也越來越低。必然有那么一天,你會發(fā)現(xiàn)云存儲的成本遠低于自建存儲的成本,到時自建存儲就會是純投入而無產(chǎn)出,也就沒有多少人會去熱衷于干這樣的事情了。
it知識庫:存儲系統(tǒng)的那些事,轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。