雲存儲的故事——元數據歸來

雲存儲服務是雲計算的重要組成部分。技術上,雲存儲屬於大型分佈式在線存儲範疇。雲存儲是一大類特殊的共享存儲。做爲提供存儲資源的服務,雲存儲須要保證用戶存放的數據可靠,不丟失。同時,雲存儲必須確保實時在線,任何宕機都會給用戶形成損失。於是,雲存儲的基本要求是高可靠和高可用。此外,雲存儲是海量數據的存儲,規模巨大。並且,出於成本和現金流量的考慮,雲存儲的集羣規模必須隨着用戶數據量的不斷增長而擴展。雲存儲的架構,設計和技術運用都是圍繞這四個基本要求展開。反之,不管多麼漂亮先進的技術,只要可能影響這些目標的實現,都不能應用於雲存儲。程序員

在我開始接觸存儲的時候,一致性哈希(以及著名的Dynamo)是很是熱門的技術。技術上一致性哈希很漂亮,簡潔,而且高效。但在實際應用中,倒是另外一種表現。本文將對集中式的元數據存儲方案和一致性哈希做對比分析,以期說明元數據是更加適合雲存儲的選擇。算法

1. 對象存儲,塊存儲數據庫

實用的雲存儲能夠分做兩類:對象存儲和塊存儲。對象存儲存儲是地道的數據倉儲,僅僅存放key/value數據:用戶有一個數據對象,須要存儲起來,他就給這個對象起一個名字(key),而後將對象連同名字一塊兒存放入對象存儲。當須要的時候,用這個名字做爲key,向存儲系統索要。而對象存儲系統必須在須要的時候將數據返還給用戶,除非用戶已將此數據從存儲系統中刪除。安全

塊存儲則是充當操做系統底下的塊設備(籠統地說,就是磁盤),供系統使用。塊存儲實際上就是一種SAN(Storage Attach Network),將集羣的存儲空間分配給用戶,掛載到操做系統,做爲磁盤使用。由於塊存儲須要模擬磁盤的行爲,所以必須確保低延遲。性能優化

儘管兩種雲存儲有徹底不一樣的目標、用途和特性,但在分佈式存儲基本特性方面都面臨着相同的問題,這裏的討論對二者都有意義。爲了簡便起見,這裏只討論對象存儲的狀況。但不少內容和結論能夠外推到塊存儲。服務器

2. 存儲的基礎網絡

雲存儲功能很是簡單,存儲用戶的數據而已。但簡單歸簡單,幾個要點仍是須要作的。當用戶將一個key-value對上傳至存儲時,存儲系統必須找合適的服務器,保存數據。一般會保存在多臺服務器上,以防止數據丟失。這叫多副本。架構

因而,一個關鍵的問題就是如何選擇存放數據的服務器。服務器的選擇是頗有技術含量的事,須要兼顧到幾個要點:首先,數據必須在服務器之間平衡。不能把數據集中到少數幾臺服務器,形成一部分服務器撐死,而另外一部分餓死。其次,在用戶讀取數據時,能夠方便快捷定位。隨後,知足雲存儲服務高可靠高可用大規模的特色。最後,儘量簡單。併發

因而,對於每一個對象,都有一個key到數據存儲位置的映射: key->pos。映射方式不少,最直接的,就是將每個對象的key->pos數據對保存下來。這些數據一般被稱爲"元數據"。運維

但還有一些更巧妙的方式:根據key的特徵,將key空間劃分紅若干分組,並將這些分組對應到不一樣的存儲節點上。這種方式能夠籠統地成爲」Sharding"。如此,能夠直接按照一個簡單規則定位到服務器。經常使用的分組方式之一是按key的區間劃分,好比a開頭的是一組,b開頭的是一組等等。而另外一種更具"現代感"的分組方式,就是對key哈希後取模。哈希方案實際上就是哈希表的天然延伸,將桶分佈到多臺服務器中。

這兩大類映射方式實質上是在不一樣的粒度上進行映射。"元數據"在對象粒度上,而sharding則是在一組對象的粒度。這兩種不一樣的粒度,決定了它們有着徹底不一樣的特性。也決定了它們在實際應用中的表現。

3. 元數據和一致性哈希

因而,在雲存儲方案中產生了兩大流派:元數據模型和Sharding模型。而Sharding模型中,一致性哈希最爲流行。一致性哈希自己很難直接用做實際使用,進而產生了不少衍生方案,其中包括著名的"Dynamo"。這裏用「一致性哈希方案」指代全部基於一致性哈希的設計。

元數據方案是對象級別的key->pos映射,也就是一個會無休止增加的"map"。每多一個對象,就會多一條元數據。一般會將元數據保存在一組數據庫中,方便檢索和查詢。元數據方案沒有什麼特別的地方,其核心是元數據存儲部分。這部分設計的好壞,關係到系統總體的特性。關於元數據存儲的設計不是本文的重點,本文將集中探討元數據方案和一致性哈希方案的比較。

標準的一致性哈希模型是對key進行哈希運算,而後投射到一個環形的數值空間上。與此同時,對節點(存儲服務器)進行編碼,而後也作哈希運算,並投射到哈希環上。理論上,只要哈希算法合適,節點能夠均勻地分佈在哈希環上。節點根據自身在哈希環上的位置,佔據一個哈希值區間,好比從本節點到下一個節點間的區間。全部落入這個區間的key,都保存到該節點上。

在這個模型中,key到數據存儲邏輯位置的映射不經過存儲,而是經過算法直接獲得。可是,邏輯位置(哈希環上的位置)到物理位置(節點)的轉換沒法直接獲得。標準的作法是任選一個節點,而後順序尋找目標節點,或者採用二分法在節點之間跳轉查找。這種查找方式在實際的存儲系統中是沒法忍受的。因此,實用的存儲系統每每採用的是一個混合模型(暫且稱之爲「混合方案」):系統維護一個哈希區間->節點的映射表。這個映射本質上也是一種元數據,可是它是大粒度的元數據,更像是一個路由表。因爲粒度大,變化不多,因此即使用文本文件均可以。這個映射表也須要多份,一般能夠存放在入口服務器上,也能夠分散到全部的存儲節點上,關鍵是保持一致便可,這相對容易。

一致性哈希解決了標準哈希表改變大小時須要從新計算,而且遷移全部數據的問題,只需遷移被新加節點佔據的哈希區間所包含的數據。可是,隨着新節點的加入,數據量的分佈會變得不均勻。爲了解決這個問題,包括Dynamo在內的諸多模型,都採用了"虛擬結點"的方案:將一個節點分紅若干虛擬節點。當節點加入系統時,把虛擬節點分散到哈希環上,如此能夠更加"均勻地"添加一個節點。

一致性哈希及其衍生方案,將數據按必定規則分片,按必定規則將分片後的數據映射到相應的存儲服務器上。所以,它只須要維護一個算法,或者一個簡單的映射表,即可直接定位數據。更加簡單,而且因爲少了查詢元數據,性能上也更有優點。

可是,這只是理論上的。

若是咱們只考慮存儲的功能(get,put,delete),一致性哈希很是完美。但實際狀況是,真正主宰雲存儲架構的,是那些非功能性需求:

一、 大規模和擴展性

二、 可靠性和一致性

三、 可用性和可管理

四、 性能

在實際的雲存儲系統中,非功能需求反而主導了架構和設計。而且對key-pos映射的選擇起到決定性的做用。

4 規模和擴展

首先,雲存儲最明顯的特色是規模巨大。對於一個公有云存儲服務,容納用戶數據是沒有限度的。不可能以"容量已滿"做爲理由,拒絕用戶存放數據。所以,雲存儲是「規模無限」的。意思就是說,雲存儲系統,必須保證任什麼時候候都可以隨意擴容,而不會影響服務。

另外一方面,雲存儲做爲服務,都是由小到大。一開始便部署幾千臺服務器,幾十P的容量,毫無心義。資源會被閒置而形成浪費,對成本和現金流量產生很大的負面做用。一般,咱們只會部署一個小規模的系統,知足初始的容量需求。而後,根據需求增加的狀況,逐步擴容。

因而,雲存儲系統必須是高度可擴展的。

面對擴展,元數據方案沒有什麼困難。當節點增長時,系統能夠更多地將新來的寫請求引導到新加入的節點。合適的調度平衡策略能夠確保系統平衡地使用各節點的存儲空間。

但對於一致性哈希和它的衍生方案而言,卻麻煩不少。原始的哈希表一旦須要擴容,須要rehash。在基於哈希的分佈式存儲系統中,這就意味着全部數據都必須從新遷移一遍。這固然沒法忍受的。一致性哈希的出現,即可以解決此問題。因爲對象和服務器都映射到哈希環上,當新節點加入後,一樣會映射到哈希環上。原來的區段會被新節點截斷,新加入的節點,會佔據被切割出來的哈希值區間。爲了完成這個轉換,這部分數據須要遷移到新服務器上。相比原始的哈希,一致性哈希只須要傳輸被新服務器搶走的那部分數據。

可是終究須要進行數據遷移。數據遷移並不是像看上去那樣,僅僅是從一臺服務器向另外一臺服務器複製數據。雲存儲是一個在線系統,數據遷移不能影響系統的服務。但遷移數據須要時間,爲了確保數據訪問的延續性,在遷移開始時,寫入操做被引導到目標服務器,而源節點的待遷移部分切換至只讀狀態。與此同時,開始從源節點遷移數據。當用戶試圖讀取遷移範圍內的數據時,須要嘗試在源和目標節點分別讀取。這種單寫雙讀的模式能夠保證服務不受影響。可是,必須控制數據遷移的速率。若是遷移操做將磁盤吞吐能力跑滿,或者網絡帶寬耗盡,服務必然受到影響。

另外一個問題是,除非成倍地增長節點,不然會存在數據不平衡的問題。爲了平衡數據,須要遷移更多的數據,每臺節點都須要遷出一些,以確保每一個節點的數據量都差很少。虛擬節點的引入即是起到這個做用。因而實際的數據遷移量同增長的容量數成正比,係數是當前存儲系統的空間使用率。

因而,一個1P的系統,三副本,70%的消耗,擴容200T,那麼須要遷移大約140T*3=420T的數據,才能使數據存儲量獲得平衡。若是使用如今經常使用的存儲服務器(2T*12),須要新增21臺。若是它們都併發起來參與遷移,單臺遷移速率不超過50MBps,那麼此次擴容所需的時間爲420T/(50M*21)=400000秒,大約4.6天。這是理想情況,包括軟硬件異常,用戶訪問壓力,遷移後的檢驗等狀況,都會延長遷移時間。極可能十天半月泡在這些任務上。而在數據遷移完成,老服務器的存儲空間回收出來以前,實際上並未擴容。那麼萬一擴容實在系統空間即將耗盡時進行,(別說這事不會碰到,一個懶散的供貨商,或者廠家被水淹,均可能讓這種事情發生。雲計算什麼事都會遇到),那麼極可能會由於來不及完成擴容而使系統停服。雲存儲,特別是公有云存儲,擴容必須是快速而便捷的。

更復雜的狀況是遷移過程當中出錯,硬件失效等異常狀況的處理過程會很複雜,由於此時數據分佈處於一種中間狀態,後續處理必須確保系統數據安全一致。

系統的擴容規模越大,困難程度越大。當系統有100P的規模(不少系統宣稱能夠達到的規模),而用戶數據增加迅猛(公有云存儲有明顯的馬太效應,規模越大,增加越快),在幾百上千臺服務器之間遷移成P的數據,是多麼駭人的場景。

數據遷移會消耗網絡帶寬,吃掉磁盤負載,攪亂服務器的cache等等,都是雲存儲的大忌,能不作儘可能不作。

元數據方案通常狀況下不須要作遷移。遷移只有存儲服務器新舊更替,或者租借的服務器到期歸還時進行。因爲數據對象能夠放置在任何節點上,於是能夠把一臺節點須要遷移的數據分散到其餘節點上。而且能夠從其餘副本那裏多對多併發地傳輸數據。負載被分散到整個集羣,對服務的影響更小,也更快捷。實際上,這個邏輯和數據副本修復是同樣的。

很顯然,相比一致性哈希方案動不動來回遷移數據的作法,元數據方案提供一個動態平衡的機制,能夠無需數據遷移,服務器一旦加入集羣,能夠馬上生效,實現平靜地擴容。

5 可靠性和一致性

可靠性(本文特指數據的可靠性,即不丟失數據)無疑是雲存儲的根本。用戶將數據託付給你,天然不但願隨隨便便地丟失。維持可靠性是雲存儲最困難的部分。(固然,更難的是在保持高可靠性的前提下確保高可用)。

在任何一個系統中,硬件和軟件都沒法保障徹底可靠。芯片會被燒燬,電路可能短路,電壓可能波動,老鼠可能咬斷網線,供電可能中斷,軟件會有bug,甚至宇宙射線會干擾寄存器…。做爲存儲的核心部件,硬盤反而更加脆弱。在標準的服務器中,除了光驅和風扇之外,硬盤是惟一的機電元件。因爲存在活動部件,其可靠性不如固態電路,更容易受到外界的干擾。因此,硬盤時常被看做消耗品。在一個有幾萬塊硬盤的存儲集羣中,每週壞上幾塊硬盤是再尋常不過的事。運氣很差的時候,一天中均可能壞上二、3塊。

所以,只把數據保存在一塊盤中是沒法保障數據可靠的。一般咱們都會將數據在不一樣的服務器上保存多份,稱之爲「副本」。原則上,副本越多,越可靠。可是,過多的副本會形成存儲成本的增長,而且下降性能,增長維持一致性的難度。通常會保持3副本,是一個比較均衡的數字。

可是,在肯定的副本數下,真正對可靠性起到關鍵做用的,是副本丟失後的恢復速度。好比,一個3副本存儲系統中,當一個磁盤損壞後,它所承載的數據對象就只剩2個副本了。在這塊盤修復以前,若是再壞一塊盤,恰巧和還沒有修復的盤有共同的數據對象,那麼這些數據就只剩一個副本在支撐着,這是很是危險的狀態。更有甚者,一個3副本的存儲系統,在運行過程當中,即使沒有硬盤損壞,總會有一些對象因爲種種緣由處於兩副本狀態,還沒有來得及修復。好比寫入數據時,有一個副本寫完後發現校驗碼不對,須要重寫。此時,若是一塊盤損壞了,上面正好有這些2副本的對象。因而,從這一刻開始,這個對象只有1副本。壞盤上的數據被修復以前,另外一塊盤包含此對象的硬盤也壞了,那麼數據就丟了。儘管這種機率很小,可是雲存儲系統是經年累月地運行,大規模加上長時間,任何小几率事件都會發生。並且在實際運行的系統中,不少因素會致使硬盤壽命遠小於理論值,好比機架震動、電源不穩、意外失電、輻射等等。並且,對於成批採購的硬盤,一般都會集中在一段時間內一塊兒進入失效期,多塊磁盤同時損壞的機率會大幅提升。

若是數據修復的速度足夠快,能夠搶在另外一塊盤損壞以前,修復丟失的副本,那麼數據丟失的機率會大大減少。(嚴格地講,不管修復時間有多短,在修復期間壞第二塊盤的機率始終存在,只是修復時間越短,這個機率越小。關鍵是要讓它小到咱們能夠接受的程度)。

一致性哈希方案中,若是將一塊磁盤同一個hash區間一一綁定。所以,數據恢復時,只能先更換壞盤,而後從其餘副本處讀取數據,寫入新磁盤。可是,磁盤的持續寫入能力一般也只有50-60MBps。若是是一塊有1.5T數據的硬盤失效,那麼恢復起來至少須要30000秒,將近9個小時。考慮到服務器的總體負載和網絡情況,時間可能會接近12小時。在這個時間尺度裏,第二塊盤,甚至第三塊盤損壞的機率仍是至關大的。並且,硬盤更換的時間取決於機房管理的響應能力,這每每是一個薄弱環節。

若是方案中讓節點同hash區間一一對應,在節點內部,再將數據分散存儲到一塊磁盤中,那麼當須要恢復副本時,節點將損壞的磁盤上的數據對象分散存放到其餘磁盤上。這樣,能夠先發起修復,從其餘副本那裏都到數據,併發地向多個磁盤恢復數據,磁盤的吞吐限制會獲得緩解。但問題的解決並不完全。首先,網絡會成爲瓶頸。1個千兆網口最多支持到120MBps,這個速率也僅僅比磁盤快一倍,並且實際使用中也不能將帶寬所有用光,不然影響服務,畢竟其餘硬盤仍是好的,還須要正常工做。原則上能夠經過增長網口數量拓寬吞吐量,但這增長了網絡設備方面的成本。並且這也僅僅是增長三、4倍的吞吐能力,咱們真正須要的是近10倍地縮小恢復時間。至於光纖,那不是普通公有云存儲所能奢望的。即使網絡吞吐問題解決了,還有一個更核心的問題。由於數據在節點內部任意分散到各磁盤上,那麼節點就須要維護一個key->磁盤的映射,也就是節點內的局部元數據。這個元數據須要服務器本身維護,因爲單臺服務器的資源有限,元數據的可靠性、可用性和一致性的維持很是麻煩。一套存儲一套元數據存儲已經夠麻煩的了,況且每一個節點一套元數據。一旦這個元數據丟失了,這個節點上全部的數據都找不到了。理論上,這個元數據丟失了,也不會影響全局,能夠利用一致性哈希算法到其餘副本那裏恢復出丟失的數據。但不得不將原來服務器上的全部數據都傳輸一遍,這個數據量每每有一二十T,恢復起來更困難。更現實的作法是直接掃描各磁盤,逆向地重建元數據。固然,這將是一個漫長的過程,期間整臺節點是不可用的,此間發生的寫入操做還需的過後從新恢復(具體參見本文「可用性」部分)。

副本恢復最快,影響最小的方法就是,不讓數據對象副本綁死在一臺節點上,只要數據對象能夠存放到任意一臺節點,那麼即可以在節點之間作多對多的數據副本恢復。集羣規模越大,速度越快,效果越好。基於元數據的方案,每個對象同節點,乃至硬盤的映射是任意的,在副本恢復方面,有得天獨厚的優點。而一致性哈希嚴格地將數據同節點或磁盤綁定,迫使這種併發沒法進行。

有一些基於混合方案的衍生方案能夠解決一致性哈希在副本修復速度問題:將哈希環劃分紅若干slot(bucket,或者其餘相似的稱謂),數量遠遠大於未來集羣可能擁有的節點數,或磁盤數。(好吧,咱們說過規模無限,無限天然不可能,只要足夠大就好了,好比2^32)。slot到節點或者磁盤的映射,經過一個映射表維護。各副本集羣中的slot分佈互不相同。當一個磁盤損壞時,找出所包含的slot,將這些slot分散到其餘節點和磁盤上去,這樣即可以併發地從其餘節點以slot爲單位恢復副本。在損壞磁盤更換以後,再將一些slot,能夠是原來的,也能夠是隨意的,遷移到新硬盤,以平衡總體的數據分佈。遷移的時候,副本已經恢復,遷移操做的時間壓力就很小了,能夠慢慢來,磁盤吞吐的瓶頸也不會有什麼的影響。

但相比之下,元數據方案修復副本以後不存在數據遷移這一步,在這方面對象級元數據的存在使副本恢復簡單不少。

同數據可靠性相關的一個問題是一致性。一致性問題能夠看做可靠性問題的一個部分。由於當各副本的數據版本不一致時,便意味着數據對象的當前版本是缺乏副本的。(實際上,從存儲角度來說,一個數據對象的不一樣版本,就是不一樣的數據)。確保一個數據對象的一致性最實用的方法是所謂W+R>N。即N個副本中,一個版本寫入時確保有W個成功,而讀取時確保有R個成功,只要知足W+R>N的狀況,即可以保證始終能夠讀到最後寫入成功的版本。

W+R>N的使用有一個問題,須要併發地從全部副本上嘗試讀取數據,而後經過讀取的數據對象版本(或者時間戳)的比對,以肯定是否知足一致性公式的要求。若是所讀取的數據有幾十上百MB,甚至上G的對象,一口氣讀出全部副本,而最終只取其中一個,着實浪費,系統壓力會整整大上N倍。解決的方法是先作一次預讀,讀出全部副本的版本信息,進行一致性比對,肯定有效副本後,再行數據自己的讀取。

元數據方案在一致性上簡單的多。元數據爲了保證可靠,也會使用多副本。由於元數據很小,能夠保持更多的副本數,好比5個,甚至7個。如此多的副本,基本上沒必要擔憂其可靠性。重點在於一致性。一樣也是採用W+R>N的策略,但卻將元數據讀取和一致性保障在一次訪問中解決。對於數據存儲服務器而言,任務更多地是在保障每個副本和版本的完整。

隨着時間的推移,數據會發生退化,有各類緣由形成副本的丟失。一致性也是同樣。對於熱數據,常常被訪問,存儲數據出錯很快就會發現。但冷數據須要依靠按期檢查發現錯誤。這個覈對工做在元數據方案裏,就是比對元數據和節點的每一個盤上的對象清單,元數據保存的永遠是最新版本,只要不匹配,就能夠認定出錯,馬上加以修復。但在一致性哈希方案中,須要交叉覈對一個哈希區間的三個副本所包含的對象清單,以肯定哪一個對象是最新副本。而後再修正數據問題。

當一個節點因爲種種緣由下線,那麼期間的全部寫入操做都沒法完成。此時,元數據方案處理起來很簡單:另外挑選一臺合適的節點,寫入副本,更新相應的元數據項後,操做完成,一切太平。

一致性哈希方案要複雜得多。對於一個哈希區間的一個副本,被固定在一個節點上。換句話說,一組副本必須存放在特定的一個節點上,不能隨意放置。若是須要定位到其餘節點上,必須整區間的遷移。這個特性的結果就是,當這臺節點下線後,沒法寫入相應的副本,也沒法隨意地將副本寫到其餘節點上。後續處理有2種方法:一、將副本或者key寫入一個隊列,等節點恢復後,發起修復操做,從其餘的副本得到數據,補上缺失的副本。問題是這個隊列必須有足夠的可靠性,不然待修復key丟失,相應的對象會長時間缺乏副本,直到數據一致性檢測發現問題。這會增長一致性檢測的壓力,使得本來就複雜的過程雪上加霜;二、按必定規則寫入其餘節點,待恢復後原樣遷移回來。這個方案相對簡單些,但整個調度邏輯比較複雜,涉及到數據節點之間的協調。可是這種點到點的數據恢復,會給暫存服務器產生壓力,不利於穩定運行。無論哪一種方案,數據遷移或者複製都是免不了的。這中間的異常處理,負載控制等都須要花費心思。

元數據方案在節點失效時的處理要比一致性哈希方案單純簡潔的多。節點失效是雲存儲的常態,處理方式越簡潔越好。在大集羣中,幾個節點同時下線都是很日常的事,一致性哈希如此複雜的節點失效管理,就是運維的地獄。

6. 可用性和可管理性

可用性在某些方面同可靠性有着共同的解決方案,好比多副本能夠消除單點,提升可用性。可是它們在其餘方面卻存在着矛盾。當一個副本寫入失敗,從可靠性角度而言,應當設法重試,或者索性告訴用戶寫入失敗。但這樣勢必形成響應變慢,或者可用性下降。(響應變慢超過一個程度後,便會被認爲是失敗,無論最終是否成功)。此外,爲了保障可靠性的諸多措施,好比副本修復,數據遷移等,會消耗系統資源,從而影響到可用性。

在上面對於可靠性的分析中能夠看到,因爲副本被綁定在特定節點上,一致性哈希要確保同元數據至關的可靠性的話,不得不放棄一些可用性,將有副本寫入出錯的操做返回失敗。由於元數據方案的數據存儲位置沒有限制,對於多數的副本寫入失敗能夠經過重選服務器獲得更正。一致性哈希則無此便利,要麼放棄必定的可用性,要麼承擔可靠性的風險。

根本上而言,一致性哈希在副本寫入上製造了局部的隱式單點,儘管是短時間的或者臨時的,但依舊會對系統產生影響。一個設計良好的分佈式系統會盡可能地減小單點出現的可能性,這直接關係到系統的持續和瞬時可用性。元數據方案能夠確保數據分佈上不存在任何形式的單點。對於一個對象而言,任何節點都沒有特殊性,這種無差異化才能真正保證消除單點。

在雲存儲系統中,使用公式R+W>N的地方,即是影響系統可用性的核心要點。可用性和一致性每每是一對冤家。在這個地方,須要向N臺服務器同時發出請求,而最終的有效性取決於服務器反饋的狀況。通常來講,N越大,越容易在確保一致性的前提下,維持可用性。(其實是取決於X=R+W-N的值,越大越好。這個值表示當X+1個副本下線或丟失後,系統將不能保證臨時的或永久的一致性)。可是,N-R和N-W越小,對可用性的影響越大。若是N=R,那麼只要有一臺服務器下線,會形成系統不可讀取。若是N-R=3,那麼即使是3臺服務器下線,系統還能正確讀取。對於W也同樣。在這裏,一致性和可用性是一對矛盾。當副本數足夠多(N數能夠很大),能夠很容易地得到較高的X數。好比N=7, R=W=5,X=3,N-R=2,N-W=2,意味着即使有2臺服務器下線,也能保證讀寫的有效性,同時確保一致性。

但若是N=3,不管如何也只能讓R=3或者W=3,此時儘管能夠得到X=3的一致性保障級別,但即使一臺服務器下線,也會形成系統不可用。若是R=W=2,能夠保證1臺服務器下線,系統仍是可用,但一致性保障級別下降到了X=1。

在元數據方案中,元數據的副本數(N)能夠大些,故障和異常形成的副本下線,或者丟失,對系統的可用性和一致性產生的影響很小,對於這類問題的處理的緊迫性會低一些。相反,一致性哈希的一致性依賴於數據存儲節點,面對大大小小的數據對象,沒法使用不少副本,一般都會用3。在這個N數下,不管一致性仍是可用性,都很脆弱。

對於可用性而言,最後,也是最重要的一點是運維管理。運維的好壞直接決定了可用性。前文已述,一致性哈希在一些關鍵的系統維護點上相比元數據方案多出很多環節。在一樣運維水平和強度下,一致性哈希更加容易出現可用性問題。這方面對可用性的影響很難明確地給出量化的評判,可是運維是雲存儲系統高可用保障的核心,運維的複雜性每每決定了最終9的個數。

如今來看看元數據方案的運維特色。元數據方案相比標準一致性哈希方案多出了一個元數據存儲系統。元數據一般有更多的副本,副本數越多,一致性的維持愈加困難。通常的方案都是依賴異步執行的版本同步機制,儘快同步各副本。可是,爲防止同步失效,會按期全面掃描覈對全部元數據,確保元數據不會退化。這個過程伴隨者很大的數據吞吐和計算量。但這個過程是離線操做,而且沒有很是嚴格的時間要求,即使失敗,也不會過多地影響系統的運行。它的時間裕度比較大。元數據量不會很大,在合適的算法下,一致性比對的時間也不會很長,一般不超過二、3小時。而且能夠根據須要增減所需的服務器數量。

一致性哈希運維的重點則在另外一頭。一致性哈希模型及其各類變形因爲須要確保數據平衡,不得不在擴容時進行大範圍的數據遷移。在不影響服務的狀況下,遷移速率必須受到限制,致使遷移時間很長。但有時數據遷移的時間要求很高。由於在遷移完成以前,遷移的數據源所佔的空間還不能回收。此時所添加的空間暫時沒法使用。並且數據回收也須要花費時間。在可用空間緊迫的狀況下,遷移速度的壓力會很大。一旦遷移過程當中出現異常,將會雪上加霜。在長達幾天的數據遷移過程當中發生磁盤損壞的可能性很是大,修復操做將迫使數據遷移減速,甚至中止。修復的優先級更高。遷移操做涉及不少服務器的併發,協調和控制工做很複雜。並且不一樣的遷移緣由會有不一樣的遷移策略。再加上各類異常處理,運維管理內容不少,將是很是痛苦的事。隨着規模愈來愈大,最終可能超出運維能力的極限,無力維持存儲的可用性。

元數據方案在絕大多數狀況下不會進行數據遷移。少掉這樣一個複雜重載的環節,對於系統維護的壓力會小不少。

所以,儘管元數據方案多出了一個元數據的存儲集羣,但它相比一致性哈希方案反而更容易維持可用性。

7. 性能

性能是大多數程序員都關心的東西,每每被放在很高的位置。但在雲存儲中,性能反卻是級別較低的問題。存儲是io密集型的系統,不管如何優化代碼,都不可避免地受到物理設備的限制。

雲存儲的性能要點首先在於併發。作好併發,確保全部請求不會相互間阻塞,即可以從大的方面保證性能。元數據方案中,元數據存取存在大量的併發訪問。每一個用戶的數據訪問請求,在這裏會轉化成N個併發請求。系統不得無論理巨大數量的併發操做,而且當心維護併發之間的邏輯關係。傳統上使用的線程池很難知足須要,不得不採用異步模型,從而增長開發難度。

一致性哈希在這方面有自身的優點。由於N數不大,併發的放大效應相比元數據方案要小不少。固然前面也說了,小N數會減少一致性的裕度,也不利於可用性。

雲存儲性能優化另外一個重要的要點是,減小一次用戶請求中跨服務器訪問的次數。跨越網絡的訪問必然存在延遲,跨的次數越多,總體延遲越大。同時也會增長網絡的負擔。元數據方案天生多一次元數據檢索操做,於是在這方面處於劣勢。但一致性哈希在讀取對象時,也沒有好到哪裏去。前面討論一致性的時候已經說過,爲了執行W+R>N的邏輯,又不能讀取全部副本,只能採起一次併發預讀操做。這樣一致性哈希的跨服務器訪問次數也同元數據方案扯平了。只是併發數少一些。這是以下降容錯能力爲代價的。

元數據在性能方面的主要劣勢是元數據的訪問。系統對元數據的訪問主要是檢索操做,所以一般會採用數據庫,或者具有檢索功能的數據存儲引擎。這些模塊在重載狀況下有性能限制。因爲副本數多,簡單地擴展服務器數量代價較大。好在這些部分的優化,特別是數據庫優化,有很成熟的經驗,花些功夫也是能作好的。

8. 其餘

在功能方面,一致性哈希還有一個不足。儘管一致性哈希能夠實現對象存儲的基本功能,但存儲服務有時須要提供一些額外的功能,好比列出一個用戶所保存的對象key清單。若是有元數據,那麼這些用戶的信息能夠保存在元數據裏,須要的時候檢索這些信息便可。可是,在一致性哈希方案中,全部的key在系統中已經被哈希,分散到全部服務器上。若是要得到用戶的對象清單,那麼就不得不在全部存儲節點上執行相應的檢索操做,想象一下一個幾千,甚至幾萬臺節點的存儲集羣,執行一次這樣的操做,會是什麼結果?

對於存放了大量數據對象的用戶,列出對象清單的操做可能沒有什麼直接意義。或許不提供此類功能,用戶也能忍受。可是,另外一個用戶相關的問題卻沒法迴避。這就是計費。計費就是計算出一個用戶全部的對象所佔據的容量,而後製做成費用清單,提供給計費系統。

計費最簡單的辦法是經過用戶的訪問記錄,累積出來,寫入就加,刪除就減。可是實際沒那麼簡單。對於一個key的覆蓋寫入,那麼必須先扣除原有的對象大小,而後再加上新對象的大小。

更重要的,因爲訪問記錄可能出錯或者丟失,這種相對計算方式隨着時間的增加會產生累積偏差。須要按期校準。校準的方式就是統計全部用戶的對象大小,作絕對容量的計算。因爲對象大小存放在全部數據存儲節點中,這又是一個恐怖的全系統的數據掃描。同時還必須確保對象屬性的一致性,以避免計費出錯。

計費涉及到錢,一般用戶會很是敏感,應當儘量不出錯。校準須要儘可能頻繁。可是全集羣的計費校準代價實在過高,仍是應當儘可能少作。因而這對矛盾怎麼調和,對於開發運維人員都是個巨大的挑戰。

在元數據方案中,計費所需信息均可以保存在元數據中,計費操做只侷限在元數據上。元數據量少,能夠直接將數據dump出來,在額外的服務器上計算。這種操做相對輕量不少,能夠更頻繁地執行,提升用戶帳單的準確性。

9. 總結

通過大致的分析,能夠看到在僅考慮雲存儲功能需求的狀況下,一致性哈希具有簡單高效的優點。可是,大型的雲存儲系統的功能不是影響其架構的主要因素。包括規模、可擴展性、可靠性、可用性和一致性等方面的非功能性需求才是雲存儲須要重點考慮的地方。一致性哈希及其各類變形方案,在這些方面存在諸多缺陷。儘管每一個方面的缺陷並不是不可逾越的障礙,每每均可以經過一些設計和運維手段加以解決。可是系統複雜度和運維難度隨之增長。最關鍵的,每一個方面的問題整合起來所產生的疊加效應,會垂手可得地摧垮一個雲存儲系統。

通常而言,一致性哈希適合一些有既定規模,不太須要擴展,數據尺寸不大的場合。這些特性意味着一致性哈希沒法很好地適用於大型的雲存儲系統。元數據方案儘管在架構上覆雜些,但其優勢是靈活。而這種靈活性更加適合雲存儲的須要。

相關文章
相關標籤/搜索