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