1. 程式人生 > >有關分散式儲存的三個基本問題 (2016-08-16 楊賽 細說雲端計算)

有關分散式儲存的三個基本問題 (2016-08-16 楊賽 細說雲端計算)

現在分散式儲存這一塊,有塊儲存、物件儲存、檔案儲存,有不同的開源專案如Ceph、GlusterFS、Sheepdog、Swift,還有不同的商業實現如Google、AWS、微軟、金山、七牛、又拍、阿里雲還有Qingcloud,思路或多或少都有些不同,可選的硬體種類也很多。似乎可選的東西太多了,而且各有優缺點。

選擇的多樣性是好事,同時也對技術選型人員的知識和能力提出了更高的要求。在本次座談會上,我們提出了有關分散式儲存的三個基本問題,邀請領域內各路專家來分享他們的解讀。本次邀請嘉賓分別是:

  • 王豪邁(麥子邁|wheats),UnitedStack工程師,擅長OpenStack、單機物理儲存、分散式儲存系統、Web應用棧等領域。OpenStack Nova、Cinder、Trove、Ceph、VirtualBox等專案的貢獻者。他的個人部落格是
    麥子邁
  • 許式偉,七牛雲端儲存CEO,《Go語言程式設計》一書作者,ECUG大會發起者。2000年畢業於南京大學,後進入金山的WPS Office事業部,從事Office軟體的研發,是WPS Office 2005的首席架構師。2007年,許式偉創立了金山實驗室,致力於雲端儲存技術的研究。2009年,許式偉離開百度加盟盛大創新院,發起了盛大祥雲計劃(盛大雲前身)。2010年10月釋出了面向個人的盛大網盤。2011年6月,許式偉離開盛大創辦了七牛,專注雲端儲存,專注為創業者服務。
  • 甘泉,青雲QingCloud聯合創始人&研發副總裁(Cofounder & VP of Engineering),具有14年軟體開發相關工作經驗。曾在華為公司、IBM 軟體實驗室任職;後在百度網頁搜尋部擔任阿拉丁產品檢索基礎架構負責人。對Linux作業系統、網路、儲存以及分散式系統架構、軟體工程等方面有比較深入的理解。
  • 王旭,MadeiraCloud CTO,在來到 Madeira Cloud 之前,曾在盛大雲進行雲硬碟(彈性塊儲存)服務的開發、在中國移動研究院進行Hadoop HDFS和彈性儲存服務的開發,是《Cassandra權威指南》的譯者。

三個基本問題分別是:

  • 對於一套分散式儲存的方案,怎樣評估它是好還是不好?
  • 如何對分散式儲存的不同實現進行分類?
  • 分散式儲存中的“資料可靠性”是如何計算的?

InfoQ:無論是在做方案的選型,還是實現一套儲存系統,權衡的因素主要考慮哪些?有沒有一套比較全面的考量/評估方式來決定哪種儲存方案更適合哪種場景?換句話說:當你去看一個儲存方案的實現,無論是看程式碼還是實測,你如何評估這套方案哪裡好,哪裡不好?

甘泉:

其實評價一個儲存方案好和不好,只有一個客觀的標準,那就是是否能滿足使用者的需求。不站在這個立場上思考這個問題,就會將技術凌駕於使用者需求之上,而技術應該是服務於使用者需求的。

那麼我們可以簡單的剖析一下使用者對儲存的需求到底是什麼。從青雲的角度來說,有以下幾點是使用者需要的:

  1. 執行或線上系統需要高效能。這個不用多說,使用者的業務資料幾乎都會儲存在資料庫裡面,沒有一個使用者會覺得資料庫效能不重要
  2. 離線或備份資料需要高容量,低價格。這部分資料通常量很大,但是對效能要求不高,對不經常用的東西也不希望負擔高額成本。
  3. 所有的資料都必須是可靠的,絕對不能丟。這是使用者對於儲存的容忍底線,所有負責任的企業都會將可靠性放在最重要的位置上,在這個基礎上能達到多高的效能就看技術實力了。

所以從上面的分析來看,之所以沒有銀彈方案,是因為使用者對儲存的需求差異很大,不同的需求需要用不同的方式來解決。這就好像現在機械 硬碟已經存在這麼多年了,磁帶依然沒有消失的原因,因為它用一種最廉價的方式解決了大容量離線資料的儲存問題,雖然它是最慢的。

王旭:

首先物件儲存和檔案儲存的區別是不大的,儲存的都是一樣的東西,只是拋棄了統一的名稱空間和目錄樹的結構,使得擴充套件起來桎梏少一些。

獨立的網際網路儲存服務一般都是做物件儲存的,因為塊儲存是給計算機用的,物件儲存是給瀏覽器等HTTP客戶端用的。獨立服務所提供的儲存系統,訪問都來自網際網路,自然是做物件儲存;與之相對應,大部分類AWS的主機服務商都會提供一個塊儲存服務搭配主機服務。

同一個服務商同時提供兩個服務是有好處的,除了提供的服務比較全這個優點以外,物件儲存還可以支撐塊儲存的快照、主機的系統映象儲存等應用,可以相互結合的。

權衡的因素有很多——可靠性要求、可用性要求、時延要求、一致性要求、使用模式相關要求(包括請求大小、QPS/IOPS、吞吐)等。

比如:

  • 對於塊儲存,要求的訪問時延是 10ms 級的,因為給虛擬機器用的,傳統硬碟也是10ms 級的時延,請求尺寸都很小,但qps(iops)可能會很高,那麼在這種情況下:
    • 異地多中心是不現實的,儲存要和主機儘量接近,相應地可靠性必然會有所打折
    • 強一致副本不會過多,強一致要求對時延有影響
  • 對於物件儲存,要求的訪問時延是 100ms - 1s 級的,請求一般是中到大尺寸,低 qps 的,在這種情況下
    • 可以用更多的分散副本數來換取更高的可靠性,但過多副本增加維持一致性的難度,需要折衷

另外SSD隨著成本降低,在塊儲存裡逐漸成為主流了,以便提供更好的IOPS,AWS這個月開始,建立的EBS卷預設就是SSD的了。

對於評價一個實現,首先是看適合不適合這個用途,然後看這個方案有沒有顯著的缺點,是否有嚴重的影響,然後成本之類的也是一個因素,做軟體的人總覺的用便宜硬體實現高大上的服務才值得吹牛,呵呵。

我得補充一點就是,做儲存這東西是需要良心的,一致性這種東西有的時候使用者是很難看出來的,偶爾一個程式出錯了,你一般不會懷疑是硬碟上存著的資料壞了,做儲存服務的人還是要儘量避免出現這種情況的。底層儲存服務(有別於資料庫)的一致性是一種很難被使用者觀測到的,但是如果一個實現根本沒達到應有的一致性,比如塊服務,只寫了一個副本就返回給應用說寫成功了,這樣是不太道德的,反正我個人堅持應該(EBS塊儲存)應該寫兩個副本再返回,在這個約束之內來優化。

也就是說,我的觀點是,先看是否滿足約束,然後看架構是否恰當,最後看細節流程的優化。

InfoQ:目前分散式儲存從應用場景、實現等層面來看,是如何分類的?

豪邁:

分散式儲存的應用場景相對於其儲存介面,現在流行分為三種:

  1. 物件儲存: 也就是通常意義的鍵值儲存,其介面就是簡單的GET、PUT、DEL和其他擴充套件,如七牛、又拍、Swift、S3

  2. 塊儲存: 這種介面通常以QEMU Driver或者Kernel Module的方式存在,這種介面需要實現Linux的Block Device的介面或者QEMU提供的Block Driver介面,如Sheepdog,AWS的EBS,青雲的雲硬碟和阿里雲的盤古系統,還有Ceph的RBD(RBD是Ceph面向塊儲存的介面)

  3. 檔案儲存: 通常意義是支援POSIX介面,它跟傳統的檔案系統如Ext4是一個型別的,但區別在於分散式儲存提供了並行化的能力,如Ceph的CephFS(CephFS是Ceph面向檔案儲存的介面),但是有時候又會把GFS,HDFS這種非POSIX介面的類檔案儲存介面歸入此類。

按照這三種介面和其應用場景,很容易瞭解這三種類型的IO特點,括號裡代表了它在非分散式情況下的對應:

  1. 物件儲存(鍵值資料庫):介面簡單,一個物件我們可以看成一個檔案,只能全寫全讀,通常以大檔案為主,要求足夠的IO頻寬。

  2. 塊儲存(硬碟):它的IO特點與傳統的硬碟是一致的,一個硬碟應該是能面向通用需求的,即能應付大檔案讀寫,也能處理好小檔案讀寫。但是硬碟的特點是容量大,熱點明顯。因此塊儲存主要可以應付熱點問題。另外,塊儲存要求的延遲是最低的。

  3. 檔案儲存(檔案系統):支援檔案儲存的介面的系統設計跟傳統本地檔案系統如Ext4這種的特點和難點是一致的,它比塊儲存具有更豐富的介面,需要考慮目錄、檔案屬性等支援,實現一個支援並行化的檔案儲存應該是最困難的。但像HDFS、GFS這種自己定義標準的系統,可以通過根據實現來定義介面,會容易一點。

因此,這三種介面分別以非分散式情況下的鍵值資料庫、硬碟和檔案系統的IO特點來對應即可。至於冷熱、快慢、大小檔案而言更接近於業務。但是因為儲存系統是通用化實現,通常來說,需要儘量滿足各種需求,而介面定義已經一定意義上就砍去了一些需求,如物件儲存會以冷儲存、大檔案為主。

實現方面,主要有兩層區別:

  1. 系統的分散式設計:主從、還是全分散式或者是兼而有之,目前現在儲存系統因為一致性的要求,以主從為主。

  2. 底層的單機儲存:一種是依賴本地檔案系統的介面,如GlusterFS,Swift,Sheepdog,Ceph。一種是依賴塊介面的,目前只知道Nutanix是使用這個的。最後一種是依賴鍵值介面的,目前應該只有Ceph是支援(Ceph支援多種單機儲存介面)。第一種依賴檔案系統是因為分散式儲存系統本身已經夠複雜,實現者很難從上層一直到底層儲存都去實現,而本地檔案系統已經是一個通用化並且非常成熟的實現,因此分散式儲存系統絕大部分(上述提到的都應該是)都會直接依賴本地檔案系統。第二種介面目前只知道Nutanix是支援的(傳統的儲存廠商的儲存產品一般會使用這種方式),這種介面也就是比第一種去掉了檔案系統層,實現一個簡單的物理塊管理即可。第三種它的主要原因是“儲存定義”和物件儲存的普及,希望硬碟來提供簡單的鍵值介面即可,如希捷的Kinetic APIFusionio NVMKV,這種介面另一方面是快閃記憶體廠商非常喜愛的,因為快閃記憶體的物理特性使得它支援鍵值介面比快介面容易得多,目前Ceph是支援這種介面,而希捷和華為最近推出了IP硬碟,聽說已經實現了Swift上的原型。

從這裡可以發現,分散式儲存系統是在傳統的單機介面上重新包裝了一層,然後實現三種類似的介面。

策略方面,三副本、多AZ六副本和網路RAID都是一類的,它們都是指資料的分佈策略來提供資料可用性,通常來說前兩者情況就是資料的多個副本分佈在所有伺服器的幾個中,也就是隻要超過副本數的伺服器掛掉,儲存系統就面臨部分資料不可用的情況。網路RAID是為了避免這種情況,比如在1000臺伺服器的情況,將其分成10臺一組的100組,這樣同樣是一份資料(Data1)的三個副本都只屬於某一個組,它不可用只當1組內(10臺)中超過3個臺機器不可用時才會發生,這樣概率會小非常多。

EC是一個類副本策略,它可以理解為增強版的複製,更少的副本可以達到更好的資料可用。

硬體方面,SSD,SAS,SATA和記憶體的組合是為了提供資料訪問的效能。千兆、萬兆甚至Inifiniband是組合是為了提供網路傳輸的效能。

許式偉:

如果我們按儲存的業務邏輯分,那麼可以分為:鍵值儲存(Key-Value Storage)、檔案系統(File System)、資料庫(Database,不是很嚴謹,只是作為所有支援多鍵值的儲存的統稱)、訊息佇列(MQ)等等。按這種分類方法儲存的種類是無窮盡的,我曾經說過 “儲存即資料結構”,表達的就是這個意思。資料結構無窮盡,儲存也會無法窮盡。塊儲存我們很少把它劃分到上面的分類中,因為它是虛擬儲存裝置,是為 VM 服務的一個東西,並不直接面向用戶業務(使用者不需要呼叫塊儲存裝置的 api 來完成業務,當然如果我們把 VM 也認為是一個業務系統的話,塊儲存也勉強可以作為一種特定的資料結構存在)。物件儲存(Object Storage)是鍵值儲存(Key-Value Storage)的特例,它假設Value是檔案,尺寸範圍可以很大(比如七牛可以支援檔案大小從0位元組到1TB)。如果要對物件儲存做進一步分類,我能夠想到的就是按實現方案來分類。比如按冗餘方案來分,可分為多副本、RAID、糾刪碼等等;或者我們按一致性方案分,可以分為主從結構和對等結構等。

不會有什麼儲存方案能夠一統天下。不同業務系統的場景需求不同,對儲存的訴求會不同,選擇自然會不同。基於糾刪碼的儲存系統,複雜性遠高於三副本的儲存系統。從易維護的角度,如果業務對儲存成本不敏感,那麼人們自然而然會選擇三副本的方案。

王旭:

除了開源服務外,這些私有的實現都沒有太公開自己的實現,不同的實現確實差異很大。但另一方面因為有共同的目標,常常有很多細節是做得差不多的,比如很多物件儲存都會把小物件放到一些預分配的大塊儲存區域裡,然後定期做compaction,來提高儲存效率、避免檔案系統碎片等。

對於塊服務,有些實現是比較簡單直接的,直接把儲存分成塊,使用者有申請,就排程到某幾臺機器上,分配一些塊,組成卷給使用者用,而有些實現是比較高層的,會先構建一個底層的分部式儲存系統,然後再從中分配塊給使用者用。後者技術含量更高一些,但一般前者的實現都屬於簡單直接型,實際效果反而更好(效能、故障處理等)一些。

InfoQ:所有做雲端儲存的都表示資料丟失是不可接受的,但資料丟失的概率——即理論上的資料可靠性(reliability),不同方案的計算方式是不同的。你們是怎麼做的,或者現在有哪些比較成熟的資料描述這個計算方法的?

Haomai:

實際上這個計算是需要依賴於儲存系統本身的。我們使用Ceph,Ceph的優勢是提供了一個叫CRush演算法的實現,可以輕鬆根據需要來規劃資料的副本數和高可用性。參考Ceph提供的模型定義來規劃自己的。這是我的同事朱榮澤做的故障計算,這個計算只針對副本策略,並不適合使用EC(擦除碼)的情況。

硬碟發生故障的概率是符合泊松分佈的。

fit = failures in time = 1/MTTF ~= 1/MTBF = AFR/(24*365)

事件概率 Pn(λ,t) = (λt)n e-λt / n!

我們對丟失資料是不能容忍的,所以只計算丟失資料的概率,不計算丟失每個object的概率。

N代表OSD的個數

R代表副本數

S代表scatter width,關係著recovery時間

我們忽略Non-Recoverable Errors的概率

計算1年內任意R個OSD發生相關故障概率的方法是

1年內OSD故障的概率。

在recovery時(R-1)個OSD發生故障的概率。

以上概率相乘。假設結果是Pr

因為任意R個OSD不一定屬於Ceph的Copy Sets,則Ceph的丟失Copy Sets的概率是:

M = Copy Sets Number

在N個OSD中,任意R個OSD的組合數是 C(R,N)

丟失Copy Sets的概率是 Pr * M / C(R, N)。

最終公式是:

P = func(N, R, S, AFR)

許式偉:

可靠性的定義可以有不同,比如有人會定義為:假設整個系統有 L 個物件,在 1 年內會損失 m 個物件,那麼可靠性為 1 - m/L。我在我那篇文章中的定義是:整個系統有 L 塊硬碟,1 年內丟失資料的概率是多少(而不管丟失了多少個物件)。

沿用文章中的可靠性定義,資料可靠性的計算涉及到以下幾個量:

  • 叢集規模-總硬碟數目(L)
  • 容錯度(M)
  • 修復速度(t)
  • 單盤可靠性(p:在t時間內損壞的概率)

我的計算方法是,先計算這L塊硬碟在t時間內同時損壞M+1塊硬碟的概率是多少(Pt,也就是丟失資料的概率,當然有細心的網友說t時間內同時損壞M+1塊盤不一定會丟失資料,這點當然是正確的,但是這個丟失資料的概率雖然不為1但是非常接近1,而且此時對軟體系統來說已經是失控狀態,為了簡化計算假設為1),然後把時間拉長到1年(T)的資料丟失概率(P)。這個拉長是非常簡單換算公式:

P = 1 - (1 - Pt)^(T/t) ≈ Pt * (T/t)

所以關鍵是計算 Pt(這L塊硬碟在t時間內同時損壞M+1塊硬碟的概率)。我們擴充套件一下,用 Pt(i) 表示 t 時間內有且僅有 i 塊盤損壞的概率。前面的 Pt 實際上是 Pt(>M),而不是 Pt(M+1)。不難得出:

Pt(>M) = 1 - Pt(0) - Pt(1) - ... - Pt(M)

好了,我們就剩下計算 Pt(i) 了。這個概率的計算比較常規:

Pt(i) = C(L, i) * p^i * (1-p)^(L-i)

其中 C(L, i) 是組合數,也就是 C(L, i) = L! / (i! * (L-i)!)

至此整個計算過程完成。不過有一個細節需要說明下,由於以下兩個原因,你無法用計算機常規的浮點數計算來得到 P:

  • C(L, i) 值會很大,甚至會超過 float64 浮點型別的最大值(約為1e308),用浮點運算最終會變 Inf(無窮大)。
  • p 非常小,這會導致計算過程精度損失非常大,計算的累計誤差無法忽略,答案和理論值大相徑庭。

所以如果你真要去算這個概率,需要用無損計算的數學包。

甘泉:

我們這個概率的計算和RAID是類似的,我們可以將RAID的概念延伸一下,其實RAID的本 質就是replication,通過多個副本來解決一個或者多個節點出問題造成的影響。所以不管是本機的副本,還是跨網路或者跨地域的副本,本質上都是在用replication做冗餘。

王旭:

其實只是丟資料的概率問題,沒有云儲存服務可以承諾絕不丟的。國內有個問題,就是——如果我在服務條款裡說了可能丟資料,那使用者就不願意用了(“雲還丟資料?!”),競爭對手的公關也要找上門來了;可是丟資料的 case 總是可能存在的,那麼,一旦丟了就是沒有盡到告知義務,而且還是會被炒作(“雲還丟資料” again),但實際上這是個 SLA 嘛,生意上的事,最後要用錢解決的嘛。

AWS的兩個主要資源層儲存服務是 EBS 和 S3,後者是物件儲存服務,強調資料可靠性,承諾11個9的 Durability,據說實際能達到更高;而EBS承諾的是年平均故障率(AFR),一年中發生塊裝置故障而導致卷無法使用的概率,這個要求實際上不高的。

對於儲存服務,物件儲存可以視為線上資料的最終儲存方案,要保證更高的可靠性,而EBS是半永久儲存方案,只有結合備份方案、多副本方案或者快照,才可以保證高可靠性的,教育使用者是雲服務行業不能迴避的任務,騙使用者說我絕對可靠是不行的,出來混是要還的。