新聞中心
一文看懂分布式存儲(chǔ)架構(gòu),這篇分析值得收藏
作者:twt社區(qū) 2020-05-12 11:38:08
存儲(chǔ)
存儲(chǔ)軟件
分布式
存儲(chǔ)架構(gòu) 在這個(gè)存儲(chǔ)系統(tǒng)中包含很多組件,除了核心的機(jī)頭(控制器)、磁盤陣列( JBOD )和交換機(jī)等設(shè)備外,還有管理設(shè)備等輔助設(shè)備。

創(chuàng)新互聯(lián)建站是一家專業(yè)提供長(zhǎng)壽企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)、H5頁(yè)面制作、小程序制作等業(yè)務(wù)。10年已為長(zhǎng)壽眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進(jìn)行中。
[[325799]]
一、集中存儲(chǔ)結(jié)構(gòu)
說到分布式存儲(chǔ),我們先來看一下傳統(tǒng)的存儲(chǔ)是怎么個(gè)樣子。
傳統(tǒng)的存儲(chǔ)也稱為集中式存儲(chǔ), 從概念上可以看出來是具有集中性的,也就是整個(gè)存儲(chǔ)是集中在一個(gè)系統(tǒng)中的,但集中式存儲(chǔ)并不是一個(gè)單獨(dú)的設(shè)備,是集中在一套系統(tǒng)當(dāng)中的多個(gè)設(shè)備,比如下圖中的 EMC 存儲(chǔ)就需要幾個(gè)機(jī)柜來存放。
在這個(gè)存儲(chǔ)系統(tǒng)中包含很多組件,除了核心的機(jī)頭(控制器)、磁盤陣列( JBOD )和交換機(jī)等設(shè)備外,還有管理設(shè)備等輔助設(shè)備。
結(jié)構(gòu)中包含一個(gè)機(jī)頭,這個(gè)是存儲(chǔ)系統(tǒng)中最為核心的部件。通常在機(jī)頭中有包含兩個(gè)控制器,互為備用, 避免硬件故障導(dǎo)致整個(gè)存儲(chǔ)系統(tǒng)的不可用。機(jī)頭中通常包含前端端口和后端端口,前端端口用戶為服務(wù)器提供存儲(chǔ)服務(wù),而后端端口用于擴(kuò)充存儲(chǔ)系統(tǒng)的容量。通過后端端口機(jī)頭可以連接更多的存儲(chǔ)設(shè)備,從而形成一個(gè)非常大的存儲(chǔ)資源池。
在整個(gè)結(jié)構(gòu)中,機(jī)頭中是整個(gè)存儲(chǔ)系統(tǒng)的核心部件,整個(gè)存儲(chǔ)系統(tǒng)的高級(jí)功能都在其中實(shí)現(xiàn)??刂破髦械能浖?shí)現(xiàn)對(duì)磁盤的管理,將磁盤抽象化為存儲(chǔ)資源池,然后劃分為 LUN 提供給服務(wù)器使用。這里的 LUN 其實(shí)就是在服務(wù)器上看到的磁盤 。當(dāng)然,一些集中式存儲(chǔ)本身也是文件服務(wù)器,可以提供共享文件服務(wù)。無論如何,從上面我們可以看出集中式存儲(chǔ) 最大的特點(diǎn)是有一個(gè)統(tǒng)一的入口,所有數(shù)據(jù)都要經(jīng)過這個(gè)入口 ,這個(gè)入口就是存儲(chǔ)系統(tǒng)的機(jī)頭。這也就是集中式存儲(chǔ)區(qū)別于分布式存儲(chǔ)最顯著的特點(diǎn)。如下圖所示:
二、分布式存儲(chǔ)
分布式存儲(chǔ)最早是由谷歌提出的,其目的是通過廉價(jià)的服務(wù)器來提供使用與大規(guī)模,高并發(fā)場(chǎng)景下的 Web 訪問問題。它 采用可擴(kuò)展的系統(tǒng)結(jié)構(gòu),利用多臺(tái)存儲(chǔ)服務(wù)器分擔(dān)存儲(chǔ)負(fù)荷,利用位置服務(wù)器定位存儲(chǔ)信息,它不但提高了系統(tǒng)的可靠性、可用性和存取效率,還易于擴(kuò)展。
1 、分布式存儲(chǔ)的興起
分布式存儲(chǔ)的興起與互聯(lián)網(wǎng)的發(fā)展密不可分,互聯(lián)網(wǎng)公司由于其數(shù)據(jù)量大而資本積累少,而通常都使用大規(guī)模分布式存儲(chǔ)系統(tǒng)。
與傳統(tǒng)的高端服務(wù)器、高端存儲(chǔ)器和高端處理器不同的是,互聯(lián)網(wǎng)公司的分布式存儲(chǔ)系統(tǒng)由數(shù)量眾多的、低成本和高性價(jià)比的普通 PC 服務(wù)器通過網(wǎng)絡(luò)連接而成。其主要原因有以下三點(diǎn)
(1) 互聯(lián)網(wǎng)的業(yè)務(wù)發(fā)展很快,而且注意成本消耗,這就使得存儲(chǔ)系統(tǒng)不能依靠傳統(tǒng)的縱向擴(kuò)展的方式,即先買小型機(jī),不夠時(shí)再買中型機(jī),甚至大型機(jī)?;ヂ?lián)網(wǎng)后端的分布式系統(tǒng)要求支持橫向擴(kuò)展,即通過增加普通 PC 服務(wù)器來提高系統(tǒng)的整體處理能力。
(2) 普通 PC 服務(wù)器性價(jià)比高,故障率也高,需要在軟件層面實(shí)現(xiàn)自動(dòng)容錯(cuò),保證數(shù)據(jù)的一致性。
(3) 另外,隨著服務(wù)器的不斷加入,需要能夠在軟件層面實(shí)現(xiàn)自動(dòng)負(fù)載均衡,使得系統(tǒng)的處理能力得到線性擴(kuò)展。
2 、分布式存儲(chǔ)的重要性
從單機(jī)單用戶到單機(jī)多用戶,再到現(xiàn)在的網(wǎng)絡(luò)時(shí)代,應(yīng)用系統(tǒng)發(fā)生了很多的變化。而分布式系統(tǒng)依然是目前很熱門的討論話題,那么,分布式系統(tǒng)給我們帶來了什么,或者說是為什么要有分布式系統(tǒng)呢?
(1)升級(jí)單機(jī)處理能力的性價(jià)比越來越低;
企業(yè)發(fā)現(xiàn)通過更換硬件做垂直擴(kuò)展的方式來提升性能會(huì)越來越不劃算;
(2)單機(jī)處理能力存在瓶頸;
某個(gè)固定時(shí)間點(diǎn),單顆處理器有自己的性能瓶頸,也就說即使愿意花更多的錢去買計(jì)算能力也買不到了;
(3)出于穩(wěn)定性和可用性的考慮
如果采用單擊系統(tǒng),那么在這臺(tái)機(jī)器正常的時(shí)候一切 OK ,一旦出問題,那么系統(tǒng)就完全不能用了。當(dāng)然,可以考慮做容災(zāi)備份等方案,而這些方案就會(huì)讓系統(tǒng)演變?yōu)榉植际较到y(tǒng)了;
(4)云存儲(chǔ)和大數(shù)據(jù)發(fā)展的必然要求
云存儲(chǔ)和大數(shù)據(jù)是構(gòu)建在分布式存儲(chǔ)之上的應(yīng)用。移動(dòng)終端的計(jì)算能力和存儲(chǔ)空間有限,而且有在多個(gè)設(shè)備之間共享資源的強(qiáng)烈的需求,這就使得網(wǎng)盤、相冊(cè)等云存儲(chǔ)應(yīng)用很快流行起來。然而,萬變不離其宗,云存儲(chǔ)的核心還是后端的大規(guī)模分布式存儲(chǔ)系統(tǒng)。大數(shù)據(jù)則更近一步,不僅需要存儲(chǔ)海量數(shù)據(jù),還需要通過合適的計(jì)算框架或者工具對(duì)這些數(shù)據(jù)進(jìn)行分析,抽取其中有價(jià)值的部分。如果沒有分布式存儲(chǔ),便談不上對(duì)大數(shù)據(jù)進(jìn)行分析。仔細(xì)分析還會(huì)發(fā)現(xiàn),分布式存儲(chǔ)技術(shù)是互聯(lián)網(wǎng)后端架構(gòu)的神器,掌握了這項(xiàng)技能,以后理解其他技術(shù)的本質(zhì)會(huì)變得非常容易。
3 、分布式存儲(chǔ)的種類和比較
分布式存儲(chǔ)包含的種類繁多,除了傳統(tǒng)意義上的分布式文件系統(tǒng)、分布式塊存儲(chǔ)和分布式對(duì)象存儲(chǔ)外,還包括分布式數(shù)據(jù)庫(kù)和分布式緩存等,但其中架構(gòu)無外乎于三種
A、 中間控制節(jié)點(diǎn)架構(gòu)
以 HDFS ( Hadoop Distribution File System )為代表的架構(gòu)是典型的代表。在這種架構(gòu)中,一部分節(jié)點(diǎn) NameNode 是存放管理數(shù)據(jù)(元數(shù)據(jù)),另一部分節(jié)點(diǎn) DataNode 存放業(yè)務(wù)數(shù)據(jù),這種類型的服務(wù)器負(fù)責(zé)管理具體數(shù)據(jù)。這種架構(gòu)就像公司的層次組織架構(gòu), namenode 就如同老板,只管理下屬的經(jīng)理( datanode ),而下屬的經(jīng)理,而經(jīng)理們來管理節(jié)點(diǎn)下本地盤上的數(shù)據(jù)。
在上圖中, 如果客戶端需要從某個(gè)文件讀取數(shù)據(jù),首先從 NameNode 獲取該文件的位置(具體在哪個(gè) DataNode ),然后從該 NameNode 獲取具體的數(shù)據(jù)。在該架構(gòu)中 NameNode 通常是主備部署( Secondary NameNode ),而 DataNode 則是由大量節(jié)點(diǎn)構(gòu)成一個(gè)集群。由于元數(shù)據(jù)的訪問頻度和訪問量相對(duì)數(shù)據(jù)都要小很多,因此 NameNode 通常不會(huì)成為性能瓶頸,而 DataNode 集群中的數(shù)據(jù)可以有副本,既可以保證高可用性,可以分散客戶端的請(qǐng)求。因此,通過這種分布式存儲(chǔ)架構(gòu)可以通過橫向擴(kuò)展 datanode 的數(shù)量來增加承載能力,也即實(shí)現(xiàn)了動(dòng)態(tài)橫向擴(kuò)展的能力。
B、 完全無中心架構(gòu) – 計(jì)算模式
以 Ceph 為代表的架構(gòu)是其典型的代表。在該架構(gòu)中與 HDFS 不同的地方在于該架構(gòu)中沒有中心節(jié)點(diǎn)??蛻舳耸峭ㄟ^一個(gè)設(shè)備映射關(guān)系 計(jì)算出來 其寫入數(shù)據(jù)的位置,這樣客戶端可以直接與存儲(chǔ)節(jié)點(diǎn)通信,從而避免中心節(jié)點(diǎn)的性能瓶頸。
如上圖所示, 在 Ceph 存儲(chǔ)系統(tǒng)架構(gòu)中核心組件有 MON 服務(wù)、 OSD 服務(wù)和 MDS 服務(wù)等。
(1) MON 服務(wù)用于維護(hù)存儲(chǔ)系統(tǒng)的硬件邏輯關(guān)系,主要是服務(wù)器和硬盤等在線信息。MON 服務(wù)通過集群的方式保證其服務(wù)的可用性。
(2) OSD 服務(wù)用于實(shí)現(xiàn)對(duì)磁盤的管理,實(shí)現(xiàn)真正的數(shù)據(jù)讀寫,通常一個(gè)磁盤對(duì)應(yīng)一個(gè) OSD 服務(wù)。
(3) MDS 只為 CephFS 文件存儲(chǔ)系統(tǒng)跟蹤文件的層次機(jī)構(gòu)和存儲(chǔ)元數(shù)據(jù)。Ceph 塊設(shè)備和 RADOS 并不需要元數(shù)據(jù),因此也不需要 Ceph MDS 守護(hù)進(jìn)程
(4) RADOS :RADOS 就是包含上述三種服務(wù)的 ceph 存儲(chǔ)集群。在 Ceph 中所有的數(shù)據(jù)都以對(duì)象形式存在的,并且無論哪種數(shù)據(jù)類型 RADOS 對(duì)象存儲(chǔ)都將負(fù)責(zé)保存這些對(duì)象。RADOS 層可以確保數(shù)據(jù)始終保持一致性。要做到這一點(diǎn)必須執(zhí)行數(shù)據(jù)復(fù)制、故障檢測(cè)和恢復(fù),以及數(shù)據(jù)遷移和所在集群節(jié)點(diǎn)實(shí)現(xiàn)在平衡
(5) RBD (塊設(shè)備):原名 RADOS 塊設(shè)備,提供可靠的分布式和高性能塊存儲(chǔ)磁盤給客戶端。
(6) CephFS :Ceph 文件系統(tǒng)提供了一個(gè)使用 Ceph 存儲(chǔ)集群存儲(chǔ)用戶數(shù)據(jù)的與 POSIX 兼容的文件系統(tǒng)
(7) Librados :libRADOS 庫(kù)為 PHP 、 RUBY 、 Java 、 Python 、 C++ 等語(yǔ)言提供 了方便的訪問 RADOS 接口的方式
(8) RADOS GW :RGW 提供對(duì)象存儲(chǔ)服務(wù),它允許應(yīng)用程序和 Ceph 對(duì)象存儲(chǔ)建立連接, RGW 提供了與 Amazon S3 和 openstack Swift 兼容的 RUSTFUL API
客戶端訪問存儲(chǔ)的大致流程是,客戶端在啟動(dòng)后會(huì)首先通過 RADOS GW 進(jìn)入,從 MON 服務(wù)拉取存儲(chǔ)資源布局信息,然后根據(jù)該布局信息和寫入數(shù)據(jù)的名稱等信息計(jì)算出期望數(shù)據(jù)的位置(包含具體的物理服務(wù)器信息和磁盤信息),然后和該位置信息對(duì)應(yīng)的 CephFS 對(duì)應(yīng)的位置直接通信,讀取或者寫入數(shù)據(jù)
C、 完全無中心架構(gòu) – 一致性哈希
以 swift 為代表的架構(gòu)是其典型的代表。與 Ceph 的通過計(jì)算方式獲得數(shù)據(jù)位置的方式不同,另外一種方式是通過一致性哈希的方式獲得數(shù)據(jù)位置。一致性哈希的方式就是將設(shè)備做成一個(gè)哈希環(huán),然后根據(jù)數(shù)據(jù)名稱計(jì)算出的哈希值映射到哈希環(huán)的某個(gè)位置,從而實(shí)現(xiàn)數(shù)據(jù)的定位。
Swift 中存在兩種映射關(guān)系,對(duì)于一個(gè)文件,通過哈希算法( MD5 )找到對(duì)應(yīng)的虛節(jié)點(diǎn)(一對(duì)一的映射關(guān)系),虛節(jié)點(diǎn)再通過映射關(guān)系( ring 文件中二維數(shù)組)找到對(duì)應(yīng)的設(shè)備(多對(duì)多的映射關(guān)系),這樣就完成了一個(gè)文件存儲(chǔ)在設(shè)備上的映射。
D 、分布式存儲(chǔ)的比較
那么現(xiàn)在問題來了,如果我們要選擇分布式存儲(chǔ),選擇哪種好呢?其實(shí)它們各有各的優(yōu)勢(shì)和使用場(chǎng)景,具體要看需求。
(1)HDFS
主要用于大數(shù)據(jù)的存儲(chǔ)場(chǎng)景,是 Hadoop 大數(shù)據(jù)架構(gòu)中的存儲(chǔ)組件。HDFS 在開始設(shè)計(jì)的時(shí)候,就已經(jīng)明確的它的應(yīng)用場(chǎng)景,就是大數(shù)據(jù)服務(wù)。主要的應(yīng)用場(chǎng)景有:
a 、對(duì)大文件存儲(chǔ)的性能比較高,例如幾百兆,幾個(gè) G 的大文件。因?yàn)?HDFS 采用的是以元數(shù)據(jù)的方式進(jìn)行文件管理,而元數(shù)據(jù)的相關(guān)目錄和塊等信息保存在 NameNode 的內(nèi)存中, 文件數(shù)量的增加會(huì)占用大量的 NameNode 內(nèi)存。如果存在大量的小文件,會(huì)占用大量?jī)?nèi)存空間,引起整個(gè)分布式存儲(chǔ)性能下降,所以盡量使用 HDFS 存儲(chǔ)大文件比較合適。
b 、適合低寫入,多次讀取的業(yè)務(wù)。就大數(shù)據(jù)分析業(yè)務(wù)而言,其處理模式就是一次寫入、多次讀取,然后進(jìn)行數(shù)據(jù)分析工作, HDFS 的數(shù)據(jù)傳輸吞吐量比較高,但是數(shù)據(jù)讀取延時(shí)比較差,不適合頻繁的數(shù)據(jù)寫入。
c 、 HDFS 采用多副本數(shù)據(jù)保護(hù)機(jī)制,使用普通的 X86 服務(wù)器就可以保障數(shù)據(jù)的可靠性,不推薦在虛擬化環(huán)境中使用。
( 2 ) Ceph
目前應(yīng)用最廣泛的開源分布式存儲(chǔ)系統(tǒng),已得到眾多廠商的支持,許多超融合系統(tǒng)的分布式存儲(chǔ)都是基于 Ceph 深度定制。而且 Ceph 已經(jīng)成為 LINUX 系統(tǒng)和 OpenStack 的 “ 標(biāo)配 ” ,用于支持各自的存儲(chǔ)系統(tǒng)。Ceph 可以提供對(duì)象存儲(chǔ)、塊設(shè)備存儲(chǔ)和文件系統(tǒng)存儲(chǔ)服務(wù)。同時(shí)支持三種不同類型的存儲(chǔ)服務(wù)的特性,在分布式存儲(chǔ)系統(tǒng)中,是很少見的。
a、 Ceph 沒有采用 HDFS 的元數(shù)據(jù)尋址的方案,而且采用 CRUSH 算法,數(shù)據(jù)分布均衡,并行度高。而且在支持塊存儲(chǔ)特性上,數(shù)據(jù)可以具有強(qiáng)一致性,可以獲得傳統(tǒng)集中式存儲(chǔ)的使用體驗(yàn)。
b、 對(duì)象存儲(chǔ)服務(wù), Ceph 支持 Swift 和 S3 的 API 接口。在塊存儲(chǔ)方面,支持精簡(jiǎn)配置、快照、克隆。在文件系統(tǒng)存儲(chǔ)服務(wù)方面,支持 Posix 接口,支持快照。但是目前 Ceph 支持文件的性能相當(dāng)其他分布式存儲(chǔ)系統(tǒng),部署稍顯復(fù)雜,性能也稍弱,一般都將 Ceph 應(yīng)用于塊和對(duì)象存儲(chǔ)。
c、 Ceph 是去中心化的分布式解決方案,需要提前做好規(guī)劃設(shè)計(jì),對(duì)技術(shù)團(tuán)隊(duì)的要求能力比較高。特別是在 Ceph 擴(kuò)容時(shí),由于其數(shù)據(jù)分布均衡的特性,會(huì)導(dǎo)致整個(gè)存儲(chǔ)系統(tǒng)性能的下降
( 3 )Swift
主要面向的是對(duì)象存儲(chǔ)。和 Ceph 提供的對(duì)象存儲(chǔ)服務(wù)類似。主要用于解決非結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)問題。它和 Ceph 的對(duì)象存儲(chǔ)服務(wù)的主要區(qū)別是。
a 、客戶端在訪問對(duì)象存儲(chǔ)系統(tǒng)服務(wù)時(shí), Swift 要求客戶端必須訪問 Swift 網(wǎng)關(guān)才能獲得數(shù)據(jù)。而 Ceph 使用一個(gè)運(yùn)行在每個(gè)存儲(chǔ)節(jié)點(diǎn)上的 OSD (對(duì)象存儲(chǔ)設(shè)備)獲取數(shù)據(jù)信息,沒有一個(gè)單獨(dú)的入口點(diǎn),比 Swift 更靈活一些。
b 、數(shù)據(jù)一致性方面, Swift 的數(shù)據(jù)是最終一致,在海量數(shù)據(jù)的處理效率上要高一些,但是主要面向?qū)?shù)據(jù)一致性要求不高,但是對(duì)數(shù)據(jù)處理效率要求比較高的對(duì)象存儲(chǔ)業(yè)務(wù)。而 Ceph 是始終跨集群強(qiáng)一致性。主要的應(yīng)用場(chǎng)景,在 OpenStack 中,對(duì)象存儲(chǔ)服務(wù)使用的就是 Swift ,而不是 Ceph 。
三、分布式理論淺析
1 、一致性和可用性
由于異常的存在,分布式存儲(chǔ)系統(tǒng)設(shè)計(jì)時(shí)往往會(huì)將數(shù)據(jù)冗余存儲(chǔ)多份,每一份稱為一個(gè)副本)。這樣,當(dāng)某一個(gè)節(jié)點(diǎn)出現(xiàn)故障時(shí),可以從其他副本上讀到數(shù)據(jù)??梢赃@么認(rèn)為,副本是分布式存儲(chǔ)系統(tǒng)容錯(cuò)技術(shù)的唯一手段。由于多個(gè)副本的存在,如何保證副本之間的一致性是整個(gè)分布式系統(tǒng)的理論核心。
數(shù)據(jù)一致性這個(gè)單詞在平常開發(fā)中,或者各種文章中都能經(jīng)??匆?,我們常常聽見什么東西數(shù)據(jù)不一致了,造成了一定的損失,趕快修復(fù)一下。那有幾種一致性呢?
a、 時(shí)間一致性:要求所有數(shù)據(jù)組件的數(shù)據(jù)在任意時(shí)刻都是完全一致的;
b、 事物一致性:事務(wù)一致性只能存在在事務(wù)開始前的和事務(wù)完成之后,在事務(wù)過程中數(shù)據(jù)有可能不一致,比如 A 轉(zhuǎn) 100 元給 B , A 扣減 100 , B 加上 100 ,在事務(wù)開始前和事務(wù)完成之后都能保證他們的帳是對(duì)上的,那么這就是事務(wù)一致性。但是在事務(wù)過程中有可能會(huì)出現(xiàn) A 扣減了 100 元, B 沒有加上 100 元的情況,這就是不一致
c、 在應(yīng)用程序中涉及多個(gè)不同的單機(jī)事務(wù),只有在所有的單機(jī)事務(wù)完成之前和完成之后,數(shù)據(jù)是完全一致的。
僅僅靠這三種一致性在實(shí)際的一些復(fù)雜場(chǎng)合是很難描述清楚的,所以,我們引出了一致性模型,這里我們由強(qiáng)到弱簡(jiǎn)單的介紹幾種常見的一致性模型。
A 、線性一致性
又稱強(qiáng)一致性, 可以看做只有一個(gè)單核處理器,或者可以看做只有一個(gè)數(shù)據(jù)副本,并且所有操作都是原子的。
如上圖所示,對(duì)于事件 e1 和 e2 來說,如果事件 e1 的 response 是在事件 e2 的 invoke 之前,我們就說 e1 happen before e2 。
對(duì)于同一個(gè)線程來說,前面的事件一定 happen before 后面的事件。但是對(duì)于不同線程上的兩個(gè)事件來說,它們之間只有在在時(shí)間線上沒有交叉的情況下,才會(huì)存在 happen before 關(guān)系。對(duì)于有交叉的那些事件,比如下圖中的 event2 和 event3 ,它們兩個(gè)就不存在 happen before 關(guān)系,對(duì)于我們要尋找的合法順序執(zhí)行過程來說,它們兩個(gè)的順序可以是任意的。
B 、順序一致性
順序一致性弱于嚴(yán)格一致性。對(duì)變量的寫操作不一定要在瞬間看到,但是,不同處理器對(duì)變量的寫操作必須在所有處理器上以相同的順序看到,這里處理器再分布式系統(tǒng)中可以換成不同的節(jié)點(diǎn)。
假設(shè)有兩個(gè)線程 A 和 B 并發(fā)執(zhí)行。其中 A 線程由 3 個(gè)操作構(gòu)成,它們?cè)诔绦蛑械捻樞蚴牵篈1->A2->A3. B 線程也有 3 個(gè)操作,它們?cè)诔绦蛑械捻樞蚴牵築1->B2->B3. 假設(shè)如果在順序一致的模型中的效果就是如上兩個(gè)圖所示。
C 、因果一致性
因果一致性是弱于順序一致性的一致性模型,順序一致性要求所有的操作的順序都必須按照某個(gè)單個(gè)處理器 ( 節(jié)點(diǎn) ) 的順序,而因果一致性只需要滿足有因果關(guān)系的操作是順序一致性即可。
簡(jiǎn)單來說如果有人問你一個(gè)問題,那么你給出答案,這兩個(gè)就是因果關(guān)系,但如果你給出答案再問題之前,那么這個(gè)就違反了因果關(guān)系。舉個(gè)簡(jiǎn)單的例子如果節(jié)點(diǎn) 1 更新了數(shù)據(jù) A ,節(jié)點(diǎn) 2 讀取數(shù)據(jù) A ,并更新數(shù)據(jù) B ,這里的數(shù)據(jù) B 有可能是根據(jù)數(shù)據(jù) A 計(jì)算出來的,所有具備因果關(guān)系,但是如果節(jié)點(diǎn) 3 看到的是先更新的 B ,再更新的 A 那么就破壞了因果一致性。
D 、最終一致性
其實(shí)除了強(qiáng)一致以外,其他的一致性都可以看作為最終一致性,只是根據(jù)一致性不同模型的不同要求又衍生出了很多具體一致性模型。當(dāng)然最簡(jiǎn)單的最終一致性,是不需要關(guān)注中間變化的順序,只需要保證在某個(gè)時(shí)間點(diǎn)一致即可。只是這個(gè)某個(gè)時(shí)間點(diǎn)需要根據(jù)不同的系統(tǒng),不同業(yè)務(wù)再去衡量。再最終一致性完成之前,有可能返回任何的值,不會(huì)對(duì)這些值做任何順序保證。
E 、可用性
可用性指“ Reads and writes always succeed” ,即服務(wù)一直可用,而且是正常響應(yīng)時(shí)間。對(duì)于一個(gè)可用性的分布式系統(tǒng),每一個(gè)非故障的節(jié)點(diǎn)必須對(duì)每一個(gè)請(qǐng)求作出響應(yīng)。所以,一般我們?cè)诤饬恳粋€(gè)系統(tǒng)的可用性的時(shí)候,都是通過停機(jī)時(shí)間來計(jì)算的。
|
可用性分類 |
可用水平(%) |
年可容忍停機(jī)時(shí)間 |
|
容錯(cuò)可用性 |
99.9999 |
<1 min |
|
極高可用性 |
99.999 |
<5 min |
|
具有故障自動(dòng)恢復(fù)能力的可用性 |
99.99 |
<53 min |
|
高可用性 |
99.9 |
<8.8h |
|
商品可用性 |
99 |
<43.8 min |
通常我們描述一個(gè)系統(tǒng)的可用性時(shí),我們說淘寶的系統(tǒng)可用性可以達(dá)到 5 個(gè) 9 ,意思就是說他的可用水平是 99.999% ,即全年停機(jī)時(shí)間不超過 (1-0.99999)36524*60 = 5.256 min ,這是一個(gè)極高的要求。
好的可用性主要是指系統(tǒng)能夠很好的為用戶服務(wù),不出現(xiàn)用戶操作失敗或者訪問超時(shí)等用戶體驗(yàn)不好的情況。一個(gè)分布式系統(tǒng),上下游設(shè)計(jì)很多系統(tǒng)如負(fù)載均衡、 WEB 服務(wù)器、應(yīng)用代碼、數(shù)據(jù)庫(kù)服務(wù)器等,任何一個(gè)節(jié)點(diǎn)的不穩(wěn)定都可以影響可用性
F 、分布式系統(tǒng)的一致性
2000 年 7 月,加州大學(xué)伯克利分校的 Eric Brewer 教授在 ACM PODC 會(huì)議上提出 CAP 猜想。2 年后,麻省理工學(xué)院的 Seth Gilbert 和 Nancy Lynch 從理論上證明了 CAP 。之后, CAP 理論正式成為分布式計(jì)算領(lǐng)域的公認(rèn)定理。
CAP 理論概述:一個(gè)分布式系統(tǒng)最多只能同時(shí)滿足一致性( Consistency )、可用性( Availability )和分區(qū)容錯(cuò)性( Partition tolerance )這三項(xiàng)中的兩項(xiàng)。
需要特別指出的 CAP 中的一致性是 all nodes see the same data at the same time ,也就是線性一致性。
一致性必須從兩個(gè)維度看:
( 1 )從客戶端角度,多進(jìn)程并發(fā)訪問時(shí),非分布式數(shù)據(jù)庫(kù)要求更新過的數(shù)據(jù)能被后續(xù)的訪問都能看到,所有都是強(qiáng)一致的;
( 2 )從服務(wù)端角度,如何盡快將更新后的數(shù)據(jù)分布到整個(gè)系統(tǒng),降低達(dá)到最終一致性的時(shí)間窗口,是提高系統(tǒng)的可用度和用戶體驗(yàn)非常重要的方面。
參考以下公式:
N — 數(shù)據(jù)復(fù)制的份數(shù)
W — 更新數(shù)據(jù)時(shí)需要保證寫完成的節(jié)點(diǎn)數(shù)
R — 讀取數(shù)據(jù)的時(shí)候需要讀取的節(jié)點(diǎn)數(shù)
(1) 如果 W+R>N ,寫的節(jié)點(diǎn)和讀的節(jié)點(diǎn)重疊,則是強(qiáng)一致性。例如對(duì)于典型的一主一備同步復(fù)制的關(guān)系型數(shù)據(jù)庫(kù), N=2,W=2,R=1 ,則不管讀的是主庫(kù)還是備庫(kù)的數(shù)據(jù),都是一致的。
(2) 如果 W+R<=N ,則是弱一致性。例如對(duì)于一主一備異步復(fù)制的關(guān)系型數(shù)據(jù)庫(kù), N=2,W=1,R=1 ,則如果讀的是備庫(kù),就可能無法讀取主庫(kù)已經(jīng)更新過的數(shù)據(jù),所以是弱一致性。
對(duì)于一個(gè)分布式系統(tǒng)來說。P 是一個(gè)基本要求, CAP 三者中,只能在 CA 兩者之間做權(quán)衡,并且要想盡辦法提升 P 。
包含兩種系統(tǒng):CP without A**、 AP without C**
我們?cè)谏衔乃岬降?Hdfs 、 Ceph 、 Swift, 均是屬于CP without A的這個(gè)大類,只是并不是完全沒有 A ,為了實(shí)現(xiàn)一定的可用性,一般設(shè)置副本的個(gè)數(shù)為 N>=3 。不同的 N,W,R 組合,是在可用性和一致性之間取一個(gè)平衡,以適應(yīng)不同的應(yīng)用場(chǎng)景。
那么,實(shí)際生活中,也有一些是AP without C的案例,如 CAP 圖中所示,大部分是 Nosql 、 CoachDB 、 Cassandra 數(shù)據(jù)庫(kù),那場(chǎng)景是哪些呢?
其實(shí)就是不要求正確性的場(chǎng)合,如某米的搶購(gòu)手機(jī)場(chǎng)景或 12306 搶購(gòu)火車票的場(chǎng)景,可能前幾秒你瀏覽商品的時(shí)候頁(yè)面提示是有庫(kù)存的,當(dāng)你選擇完商品準(zhǔn)備下單的時(shí)候,系統(tǒng)提示你下單失敗,商品已售完。這其實(shí)就是先在 A(可用性)方面保證系統(tǒng)可以正常的服務(wù),然后在數(shù)據(jù)的一致性方面做了些犧牲。
2 、數(shù)據(jù)分布
分布式系統(tǒng)區(qū)別于傳統(tǒng)單機(jī)系統(tǒng)在于能夠?qū)?shù)據(jù)分布到多個(gè)節(jié)點(diǎn),并在多個(gè)節(jié)點(diǎn)之間實(shí)現(xiàn)負(fù)載均衡。數(shù)據(jù)分布的方式主要有兩種,一種是哈希分布,如一致性哈希,代表系統(tǒng)為
Amazon 的 Dynamo 系統(tǒng), Openstack 的 Swift 系統(tǒng);另外一種方法是順序分布,即每張表格上的數(shù)據(jù)按照主鍵整體有序,代表系統(tǒng)為 Google 的 Bigtable 系統(tǒng)。Bigtable 將一張大表根據(jù)主鍵切分為有序的范圍,每個(gè)有序范圍是一個(gè)子表。
A 、哈希分布( Swift )
哈希函數(shù)的散列特性很好,哈希方式可以將數(shù)據(jù)比較均勻地分布到集群中去。而且,哈希方式需要記錄的元信息也非常簡(jiǎn)單,每個(gè)節(jié)點(diǎn)只需要知道哈希函數(shù)的計(jì)算方式以及模的服務(wù)器的個(gè)數(shù)就可以計(jì)算出處理的數(shù)據(jù)應(yīng)該屬于哪臺(tái)機(jī)器。
然而,找出一個(gè)散列特性很好的哈希函數(shù)是很難的。這是因?yàn)?,如果按照主鍵散列,那么同一個(gè)用戶 id 下的數(shù)據(jù)可能被分散到多臺(tái)服務(wù)器,這會(huì)使得一次操作同一個(gè)用戶 id 下的多條記錄變得困難;如果按照用戶 id 散列,容易出現(xiàn) “ 數(shù)據(jù)傾斜 ” ( data skew )問題,即某些大用戶的數(shù)據(jù)量很大,無論集群的規(guī)模有多大,這些用戶始終由一臺(tái)服務(wù)器處理。
處理大用戶問題一般有兩種方式,一種方式是手動(dòng)拆分,即線下標(biāo)記系統(tǒng)中的大用戶(例如運(yùn)行一次 MapReduce 作業(yè)),并根據(jù)這些大用戶的數(shù)據(jù)量將其拆分到多臺(tái)服務(wù)器上。這就相當(dāng)于在哈希分布的基礎(chǔ)上針對(duì)這些大用戶特殊處理;
另一種方式是自動(dòng)拆分,即數(shù)據(jù)分布算法能夠動(dòng)態(tài)調(diào)整,自動(dòng)將大用戶的數(shù)據(jù)拆分到多臺(tái)服務(wù)器上。其中包含兩種算法。
一種是傳統(tǒng)的哈希算法,訪問數(shù)據(jù)時(shí),首先計(jì)算哈希值,再查詢?cè)獢?shù)據(jù)服務(wù)器,獲得該哈希值對(duì)應(yīng)的服務(wù)器。在這種算法下,服務(wù)器的上線和下線將導(dǎo)致大量的數(shù)據(jù)遷移,不適合于生產(chǎn)。
另一致性哈希( Distributed Hash Table,DHT )算法。算法思想如下:給系統(tǒng)中每個(gè)節(jié)點(diǎn)分配一個(gè)隨機(jī) token ,這些 token 構(gòu)成一個(gè)哈希環(huán)。執(zhí)行數(shù)據(jù)存放操作時(shí),先計(jì)算 Key (主鍵)的哈希值,然后存放到順時(shí)針方向第一個(gè)大于或者等于該哈希值的 token 所在的節(jié)點(diǎn)。一致性哈希的優(yōu)點(diǎn)在于節(jié)點(diǎn)加入 / 刪除時(shí)只會(huì)影響到在哈希環(huán)中相鄰的節(jié)點(diǎn),而對(duì)其他節(jié)點(diǎn)沒影響。
如上圖所示,算法本身的特性可以使得 磁盤劃分為比較多的較為均勻的虛擬分區(qū),每個(gè)虛擬分區(qū)是哈希環(huán)上的一個(gè)節(jié)點(diǎn),整個(gè)環(huán)是從 0 到 32 位最大值的一個(gè)區(qū)間,并且首尾相連,當(dāng)計(jì)算出數(shù)據(jù)(或者數(shù)據(jù)名稱)的哈希值后,必然落到哈希環(huán)的某個(gè)區(qū)間,然后以順時(shí)針,必然能夠找到一個(gè)節(jié)點(diǎn)。那么這個(gè)節(jié)點(diǎn)就是存儲(chǔ)數(shù)據(jù)的位置。可見如果只有一個(gè)節(jié)點(diǎn),最大到 32 還未找到節(jié)點(diǎn),那么數(shù)據(jù)就在第一個(gè)唯一節(jié)點(diǎn)上。
整個(gè)的數(shù)據(jù)定位就是基于上述的一致算法,實(shí)現(xiàn)將請(qǐng)求重新定向到該設(shè)備進(jìn)行處理
(1) 在對(duì)象存儲(chǔ)上,通過賬戶名 / 容器名 / 對(duì)象名三個(gè)名稱組成一個(gè)位置的標(biāo)識(shí),通過該唯一標(biāo)識(shí)可以計(jì)算出一個(gè)整型數(shù);
(2) 存儲(chǔ)設(shè)備方面, Swift 構(gòu)建一個(gè)虛擬分區(qū)表,表的大小在創(chuàng)建集群是確定(通常為幾十萬),這個(gè)表其實(shí)就是一個(gè)數(shù)組;
(3) 整數(shù)值和這個(gè)數(shù)組,通過一致性哈希算法就可以確定該整數(shù)在數(shù)組的位置。
一致性算法原理上可以保證數(shù)據(jù)的均衡性、單調(diào)性,避免數(shù)據(jù)的分散性,有效的保證數(shù)據(jù)的一致性,使得負(fù)載盡可能的被映射到一個(gè)特定的緩存區(qū)。
因?yàn)?一致性哈希算法在服務(wù)節(jié)點(diǎn)太少時(shí),容易因?yàn)楣?jié)點(diǎn)分部不均勻而造成數(shù)據(jù)傾斜問題。所以在實(shí)際應(yīng)用中,通常將虛擬節(jié)點(diǎn)數(shù)設(shè)置為比 32 更大的值,因此即使很少的服務(wù)節(jié)點(diǎn)也能做到相對(duì)均勻的數(shù)據(jù)分布。
B 、順序分布( Bigtable )
哈希散列破壞了數(shù)據(jù)的有序性,只支持隨機(jī)讀取操作,不能夠支持順序掃描。某些系統(tǒng)可以在應(yīng)用層做折衷,比如互聯(lián)網(wǎng)應(yīng)用經(jīng)常按照用戶來進(jìn)行數(shù)據(jù)拆分,并通過哈希方法進(jìn)行數(shù)據(jù)分布,同一個(gè)用戶的數(shù)據(jù)分布到相同的存儲(chǔ)節(jié)點(diǎn),允許對(duì)同一個(gè)用戶的數(shù)據(jù)執(zhí)行順序掃描,由應(yīng)用層解決跨多個(gè)用戶的操作問題。另外,這種方式可能出現(xiàn)某些用戶的數(shù)據(jù)量太大的問題,由于用戶的數(shù)據(jù)限定在一個(gè)存儲(chǔ)節(jié)點(diǎn),無法發(fā)揮分布式存儲(chǔ)系統(tǒng)的多機(jī)并行處理能力。
順序分布在分布式表格系統(tǒng)( Bigtable )中比較常見,一般的做法是將大表順序劃分為連續(xù)的范圍,每個(gè)范圍稱為一個(gè)子表,總控服務(wù)器負(fù)責(zé)將這些子表按照一定的策略分配到存儲(chǔ)節(jié)點(diǎn)上。
如圖所示,用戶表( User 表)的主鍵范圍為 1 ~ 7000 ,在分布式存儲(chǔ)系統(tǒng)中劃分為多個(gè)子表,分別對(duì)應(yīng)數(shù)據(jù)范圍 1 ~ 1000 , 1001 ~ 2000 , ……6001 ~ 7000 。其中 Meta 表是為了支持更大的集群規(guī)模,它將原來的一層索引結(jié)分成兩層,使用 Meta 表來維護(hù) User 子表所在的節(jié)點(diǎn),從而減輕 Root 節(jié)點(diǎn)的負(fù)擔(dān)。
順序分布與 B+ 樹數(shù)據(jù)結(jié)構(gòu)比較類似,每個(gè)子表相當(dāng)于葉子節(jié)點(diǎn),隨著數(shù)據(jù)的插入和刪除,某些子表可能變得很大,某些變得很小,數(shù)據(jù)分布不均勻。如果采用順序分布,系統(tǒng)設(shè)計(jì)時(shí)需要考慮子表的分裂與合并,這將極大地增加系統(tǒng)復(fù)雜度。
C 、 CRUSH 分布
CRUSH 算法,全稱叫 Controlled, Scalable, Decentralized Placement of Replicated Data. 嚴(yán)格說起來 Crush 算法,其實(shí)也是以 Hash 算法為基礎(chǔ)的。只不過映射的方法和一致性哈希不同。我們用 Ceph 分布的過程來加以說明。
Ceph 分布數(shù)據(jù)的過程:首先計(jì)算數(shù)據(jù) x 的 Hash 值并將結(jié)果和 PG 數(shù)目取余,以得到數(shù)據(jù) x 對(duì)應(yīng)的 PG 編號(hào)。然后,通過 CRUSH 算法將 PG 映射到一組 OSD 中。最后把數(shù)據(jù) x 存放到 PG 對(duì)應(yīng)的 OSD 中。注明:PG 全稱是 Placement Group (放置組)。
這個(gè)過程中包含了兩次映射,第一次是數(shù)據(jù) x 到 PG 的映射。如果把 PG 當(dāng)作存儲(chǔ)節(jié)點(diǎn),那么傳統(tǒng) Hash 算法一樣。不同的是, PG 是抽象的存儲(chǔ)節(jié)點(diǎn),它不會(huì)隨著物理節(jié)點(diǎn)的加入或則離開而增加或減少,因此數(shù)據(jù)到 PG 的映射是穩(wěn)定的。
以 Dynamo 為例,在這個(gè)過程中, PG 起到了兩個(gè)作用:第一個(gè)作用是劃分?jǐn)?shù)據(jù)分區(qū)。每個(gè) PG 管理的數(shù)據(jù)區(qū)間相同,因而數(shù)據(jù)能夠均勻地分布到 PG 上;第二個(gè)作用是充當(dāng) Dynamo 中 Token 的角色,即決定分區(qū)位置。實(shí)際上,這和 Dynamo 中固定分區(qū)數(shù)目,以及維持分區(qū)數(shù)目和虛擬節(jié)點(diǎn)數(shù)目相等的原則是同一回事。
以 Ceph 為例, CRUSH 算法通過兩次映射計(jì)算數(shù)據(jù)存儲(chǔ)位置來確定如何存儲(chǔ)和檢索數(shù)據(jù)。CRUSH 使 Ceph 客戶機(jī)能夠直接與 OSDs 通信,而不是通過集中的服務(wù)器或代理。
通過算法確定的數(shù)據(jù)存儲(chǔ)和檢索方法, Ceph 避免了單點(diǎn)故障、性能瓶頸和對(duì)其可伸縮性的物理限制。CRUSH 需要集群的映射,并使用 CRUSH 映射在 OSDs 中偽隨機(jī)存儲(chǔ)和檢索數(shù)據(jù),數(shù)據(jù)在集群中均勻分布。
3 、復(fù)制
為了保證分布式存儲(chǔ)系統(tǒng)的高可靠和高可用,數(shù)據(jù)在系統(tǒng)中一般存儲(chǔ)多個(gè)副本。當(dāng)某個(gè)副本所在的存儲(chǔ)節(jié)點(diǎn)出現(xiàn)故障時(shí),分布式存儲(chǔ)系統(tǒng)能夠自動(dòng)將服務(wù)切換到其他的副本,從而實(shí)現(xiàn)自動(dòng)容錯(cuò)。分布式存儲(chǔ)系統(tǒng)通過復(fù)制協(xié)議將數(shù)據(jù)同步到多個(gè)存儲(chǔ)節(jié)點(diǎn),并確保多個(gè)副本之間的數(shù)據(jù)一致性。
A 、強(qiáng)同步復(fù)制
客戶端將寫請(qǐng)求發(fā)送給主副本,主副本將寫請(qǐng)求復(fù)制到其他備副本,常見的做法是同步操作日志( Commit Log )。主副本首先將操作日志同步到備副本,備副本回放操作日志,完成后通知主副本。接著,主副本修改本機(jī),等到所有的操作都完成后再通知客戶端寫成功。下圖中的復(fù)制協(xié)議要求主備同步成功才可以返回客戶端寫成功,這種協(xié)議稱為強(qiáng)同步協(xié)議。
假設(shè)所有副本的個(gè)數(shù)為 N ,且 N > 2 ,即備副本個(gè)數(shù)大于 1 。那么,實(shí)現(xiàn)強(qiáng)同步協(xié)議時(shí),主副本可以將操作日志并發(fā)地發(fā)給所有備副本并等待回復(fù),只要至少 1 個(gè)備副本返回成功就可以回復(fù)客戶端操作成功。強(qiáng)同步的好處在于如果主副本出現(xiàn)故障,至少有 1 個(gè)備副本擁有完整的數(shù)據(jù),分布式存儲(chǔ)系統(tǒng)可以自動(dòng)地將服務(wù)切換到最新的備副本而不用擔(dān)心數(shù)據(jù)丟失的情況。
B 、異步復(fù)制
與強(qiáng)同步對(duì)應(yīng)的復(fù)制方式是異步復(fù)制。在異步模式下,主副本不需要等待備副本的回應(yīng),只需要本地修改成功就可以告知客戶端寫操作成功。另外,主副本通過異步機(jī)制,比如單獨(dú)的復(fù)制線程將客戶端修改操作推送到其他副本。異步復(fù)制的好處在于系統(tǒng)可用性較好,但是一致性較差,如果主副本發(fā)生不可恢復(fù)故障,可能丟失最后一部分更新操作。
C 、 NWR 復(fù)制
分布式存儲(chǔ)系統(tǒng)中還可能使用基于寫多個(gè)存儲(chǔ)節(jié)點(diǎn)的復(fù)制協(xié)議( Replicated-write protocol )。比如 Dynamo 系統(tǒng)中的 NWR 復(fù)制協(xié)議,其中, N 為副本數(shù)量, W 為寫操作的副本數(shù), R 為讀操作的副本數(shù)。
NWR 協(xié)議中多個(gè)副本不再區(qū)分主和備,客戶端根據(jù)一定的策略往其中的 W 個(gè)副本寫入數(shù)據(jù),讀取其中的 R 個(gè)副本。只要 W+R > N ,可以保證讀到的副本中至少有一個(gè)包含了最新的更新。然而,這種協(xié)議的問題在于不同副本的操作順序可能不一致,從多個(gè)副本讀取時(shí)可能出現(xiàn)沖突。這種方式在實(shí)際系統(tǒng)中比較少見,不建議使用。
4 、分布式協(xié)議
分布式協(xié)議有很多,其中以兩階段提交和 Paxos 協(xié)議最具代表性。兩階段提交協(xié)議( 2PC )或三階段提交( 3PC )用于保證跨多個(gè)節(jié)點(diǎn)操作的原子性,也就是說,跨多個(gè)節(jié)點(diǎn)的操作要么在所有節(jié)點(diǎn)上全部執(zhí)行成功,要么全部失敗。Paxos 協(xié)議用于確保多個(gè)節(jié)點(diǎn)對(duì)某個(gè)投票(例如哪個(gè)節(jié)點(diǎn)為主節(jié)點(diǎn))達(dá)成一致。
A 、兩階段提交
二階段提交的算法思路可以概括為 : 參與者將操作成敗通知協(xié)調(diào)者,再由協(xié)調(diào)者根據(jù)所有參與者的反饋情報(bào)決定各參與者是否要提交操作還是中止操作。
(1)請(qǐng)求階段 ( 表決 ) :
事務(wù)協(xié)調(diào)者協(xié)調(diào)者通知事務(wù)參與者準(zhǔn)備提交或者取消事務(wù),然后進(jìn)入表決過程。在表決過程中,參與者將告知協(xié)調(diào)者自己的決策:同意(事務(wù)參與者本地執(zhí)行成功)或者取消(事務(wù)參與者本地執(zhí)行失敗)。
(2)提交階段 ( 執(zhí)行 ):
在該階段,協(xié)調(diào)者將基于第一個(gè)階段的投票結(jié)果進(jìn)行決策 : 提交或取消,當(dāng)且僅當(dāng)所有的參與者同意提交事務(wù),協(xié)調(diào)者才通知所有的參與者提交事務(wù),否則協(xié)調(diào)者將通知所有的參與者取消事務(wù)參與者在接收到協(xié)調(diào)者發(fā)來的消息后將執(zhí)行響應(yīng)的操作。
(3)兩階段提交無法解決的問題
A )、如果一個(gè)參與者遲遲不投票,那整個(gè)階段都會(huì)處于等待狀態(tài),但這可以通過超時(shí)機(jī)制解決
B )、當(dāng)協(xié)調(diào)者出錯(cuò),同時(shí)參與者也出錯(cuò)時(shí),兩階段無法保證事務(wù)執(zhí)行的完整性。
考慮協(xié)調(diào)者在發(fā)出 commit 消息之后宕機(jī),而唯一接收到這條消息的參與者同時(shí)也宕機(jī)了。
那么即使協(xié)調(diào)者通過選舉協(xié)議產(chǎn)生了新的協(xié)調(diào)者,這條事務(wù)的狀態(tài)也是不確定的,沒人知道事務(wù)是否被已經(jīng)提交。
B 、三階段提交
三階段提交擁有 CanCommit 、 PreCommit 、 DoCommit 三個(gè)階段
( 1 )其中 CanCommit 階段近似等同于兩階段的請(qǐng)求階段;DoCommit 近似等同于兩階段的提交階段。而準(zhǔn)備階段 PreCommit 是一個(gè)緩沖,保證了在最后提交階段之前各參與節(jié)點(diǎn)的狀態(tài)是一致的。
( 2 )三階段提交在兩階段提交的第一階段與第二階段之間插入了一個(gè)準(zhǔn)備階段( PreCommit ),使得原先在兩階段提交中,參與者在投票之后,由于協(xié)調(diào)者發(fā)生崩潰或錯(cuò)誤,而導(dǎo)致參與者處于無法知曉是否提交或者中止的“不確定狀態(tài)”所產(chǎn)生的可能相當(dāng)長(zhǎng)的延時(shí)的問題得以解決。
( 3 )三階段提交無法解決的問題
如果進(jìn)入 PreCommit 后,協(xié)調(diào)者發(fā)出的是 commit 請(qǐng)求,假設(shè)只有一個(gè)參與者收到并進(jìn)行了 commit 操作,而其他參與者對(duì)于網(wǎng)絡(luò)中斷沒有收到,會(huì)根據(jù) 3PC 選擇 abort 操作,此時(shí)系統(tǒng)狀態(tài)發(fā)生不一致性。
C 、 Paxos 協(xié)議
要講 Paxos ,先要從拜占庭問題講起,其故事背景是這樣的:拜占庭位于現(xiàn)在土耳其的伊斯坦布爾,是東羅馬帝國(guó)的首都。由于當(dāng)時(shí)拜占庭羅馬帝國(guó)國(guó)土遼闊,為了防御目的,因此每個(gè)軍隊(duì)都分隔很遠(yuǎn),將軍與將軍之間只能靠信差傳消息。在戰(zhàn)爭(zhēng)的時(shí)候,拜占庭軍隊(duì)內(nèi)所有將軍必需達(dá)成一致的共識(shí),決定是否有贏的機(jī)會(huì)才去攻打敵人的陣營(yíng)。但是,軍隊(duì)可能有叛徒和敵軍間諜,這些叛徒將軍們會(huì)擾亂或左右決策的過程。這時(shí)候,在已知有成員謀反的情況下,其余忠誠(chéng)的將軍在不受叛徒的影響下如何達(dá)成一致的協(xié)議,這就是拜占庭將軍問題。
我們否定假設(shè),給出了非拜占庭模型定義:
( 1 )一致性模塊的行為可以以任意速度執(zhí)行,允許運(yùn)行失敗,在失敗后也許會(huì)重啟并再次運(yùn)行;
( 2 )一致性模塊之間通過異步方式發(fā)送信息通信,通信時(shí)間可以任意長(zhǎng),信息可能會(huì)在傳輸過程中丟失,也允許重復(fù)發(fā)送相同的信息,多重信息的順序可以任意。但是有一點(diǎn):信息不允許被篡改。
由此,我們得出了 Paxos 的基本二階段:Prepare 階段、 Accept 階段,這個(gè)兩個(gè)階段的邏輯非常復(fù)雜,是互信算法的基礎(chǔ),本文并不打算做過深的解讀。有興趣的讀者可以去參考《區(qū)塊鏈算法》一書。
D 、 Raft 協(xié)議
Raft 是 Replicated And Fault Tolerant 的縮寫, Paxos 的簡(jiǎn)化版本。
在一個(gè)分布式系統(tǒng)中,要提高系統(tǒng)的健壯性,可用性和數(shù)據(jù)的安全性,我們最正確的姿勢(shì)是什么?當(dāng)然是靠多備份了,服務(wù)多備份,數(shù)據(jù)多備份,去除單點(diǎn),確保即使相關(guān)組件掛掉一些,系統(tǒng)還能健康服務(wù)。
去除單點(diǎn),沒有固定不變的權(quán)威,固然好,但是帶來的問題就是,以誰(shuí)的意見為準(zhǔn),在信息可能丟失的環(huán)境下,這是一個(gè)相當(dāng)困難的事(可見溝通是多么的重要)!
在 1990 年提出來之時(shí),幾乎沒有人能夠理解。經(jīng)過作者多次簡(jiǎn)化,再解釋,包括谷歌等團(tuán)隊(duì)的實(shí)踐再創(chuàng)造,再解釋的過程,十幾年過去了,才漸漸的成為事實(shí)標(biāo)準(zhǔn)并被大家所了解和接受。但直到現(xiàn)在,無比抽象的 Paxos 算法,還是沒有幾個(gè)人能理解。
大道至簡(jiǎn)!這是永恒不變的真理, Raft 的目標(biāo)問題,是構(gòu)建一個(gè)容易理解和構(gòu)建的分布式一致性協(xié)議,在容易的基礎(chǔ)上,確保理論正確的。
Raft 協(xié)議,如果照本宣讀,還是需要點(diǎn)時(shí)間的,本文采用通俗的辦法給大家做解釋
Raft 大致的原理,這是一個(gè)選主( leader selection )思想的算法,集群總每個(gè)節(jié)點(diǎn)都有三種可能的角色:
( 1 ) leader
對(duì)客戶端通信的入口,對(duì)內(nèi)數(shù)據(jù)同步的發(fā)起者,一個(gè)集群通常只有一個(gè) leader 節(jié)點(diǎn)
( 2 ) follower:
非 leader 的節(jié)點(diǎn),被動(dòng)的接受來自 leader 的數(shù)據(jù)請(qǐng)求
( 3 ) candidate:
一種臨時(shí)的角色,只存在于 leader 的選舉階段,某個(gè)節(jié)點(diǎn)想要變成 leader ,那么就發(fā)起投票請(qǐng)求,同時(shí)自己變成 candidate 。如果選舉成功,則變?yōu)?candidate ,否則退回為 follower 。
算法包含兩個(gè)過程:leader 選舉和日志復(fù)制:
(1) 選舉過程:(假設(shè)有 5 個(gè)節(jié)點(diǎn), S1~S5 )
a、 初始狀態(tài)下,大家都是平等的 follower ,那么 follow 誰(shuí)呢,總要選個(gè)老大吧。大家都蠢蠢欲動(dòng),每個(gè) follower 內(nèi)部都維護(hù)了一個(gè)隨機(jī)的 timer ;
b、 在 timer 時(shí)間到了的時(shí)候還沒有人主動(dòng)聯(lián)系它的話,那它就要變成 candidate ,同時(shí)發(fā)出投票請(qǐng)求( RequestVote )給其他人,假設(shè) S1, S3 成為 candidate
c、 對(duì)于相同條件的 candidate , follower 們采取先來先投票的策略。如果超過半數(shù)的 follower 都認(rèn)為他是合適做領(lǐng)導(dǎo)的,那么恭喜,新的 leader 產(chǎn)生了,假如 S3 變成了新一屆的大哥 leader ;
d、 S1 很不幸,沒有人愿意選這個(gè)悲劇的 candidate ,那它只有老老實(shí)實(shí)的變回小弟的狀態(tài) follower;
e、 同樣的,如果在 timer 期間內(nèi)沒有收到大哥的聯(lián)絡(luò),這時(shí)很可能大哥已經(jīng)跪了,如下圖,所有小弟又開始蠢蠢欲動(dòng),新的一輪 (term) 選舉開始了。
(2) 日志復(fù)制:(假設(shè)有 5 個(gè)節(jié)點(diǎn), S1~S5 )
a、 leader 扮演的是分布式事務(wù)中的協(xié)調(diào)者,每次有數(shù)據(jù)更新的時(shí)候產(chǎn)生二階段提交( two-phase commit )。在 leader 收到數(shù)據(jù)操作的請(qǐng)求,先不著急更新本地?cái)?shù)據(jù)(數(shù)據(jù)是持久化在磁盤上的),而是生成對(duì)應(yīng)的 log ,然后把生成 log 的請(qǐng)求廣播給所有的 follower ;
b、 每個(gè) follower 在收到請(qǐng)求之后有兩種選擇:一種是聽從 leader 的命令,也寫入 log ,然后返回 success 回去;另一種情況,在某些條件不滿足的情況下, follower 認(rèn)為不應(yīng)該聽從 leader 的命令,返回 false ;
c、 此時(shí)如果超過半數(shù)的 follower 都成功寫了 log ,那么 leader 開始_第二階段_的提交:正式寫入數(shù)據(jù),然后同樣廣播給 follower , follower 也根據(jù)自身情況選擇寫入或者不寫入并返回結(jié)果給 leader ,最終所有節(jié)點(diǎn)的數(shù)據(jù)達(dá)成一致。
d、 這兩階段中如果任意一個(gè)都有超過半數(shù)的 follower 返回 false 或者根本沒有返回,那么這個(gè)分布式事務(wù)是不成功的。此時(shí)雖然不會(huì)有回滾的過程,但是由于數(shù)據(jù)不會(huì)真正在多數(shù)節(jié)點(diǎn)上提交,所以會(huì)在之后的過程中被覆蓋掉
Raft 協(xié)議保證_leader_的強(qiáng)領(lǐng)導(dǎo)地位 ,client _讀寫都_通過_leader__,有很高的一致性,但有些同學(xué)會(huì)問,那分布式的價(jià)值在什么地方呢?如何才能負(fù)載均衡呢?在實(shí)際中我們采用 Multi Raft 架構(gòu),結(jié)合應(yīng)用,不同的應(yīng)用選舉不同的 leader 節(jié)點(diǎn),在負(fù)載均衡。
5、跨機(jī)房部署
在分布式系統(tǒng)中,跨機(jī)房問題一直都是老大難問題。機(jī)房之間的網(wǎng)絡(luò)延時(shí)較大,且不穩(wěn)定??鐧C(jī)房問題主要包含兩個(gè)方面:數(shù)據(jù)同步以及服務(wù)切換。跨機(jī)房部署方案有三個(gè):集群整體切換、單個(gè)集群跨機(jī)房、 Paxos 選主副本。下面分別介紹。
A 、集群整體切換
集群整體切換是最為常見的方案。如圖所示,假設(shè)某系統(tǒng)部署在兩個(gè)機(jī)房:機(jī)房 1 和機(jī)房 2 。兩個(gè)機(jī)房保持獨(dú)立,每個(gè)機(jī)房部署單獨(dú)的總控節(jié)點(diǎn),且每個(gè)總控節(jié)點(diǎn)各有一個(gè)備份節(jié)點(diǎn)。當(dāng)總控節(jié)點(diǎn)出現(xiàn)故障時(shí),能夠自動(dòng)將機(jī)房?jī)?nèi)的備份節(jié)點(diǎn)切換為總控節(jié)點(diǎn)繼續(xù)提供服務(wù)。另外,兩個(gè)機(jī)房部署了相同的副本數(shù),例如數(shù)據(jù)分片 A 在機(jī)房 1 存儲(chǔ)的副本為 A11 和 A12 ,在機(jī)房 2 存儲(chǔ)的副本為 A21 和 A22 。在某個(gè)時(shí)刻,機(jī)房 1 為主機(jī)房,機(jī)房 2 為備機(jī)房。
機(jī)房之間的數(shù)據(jù)同步方式可能為強(qiáng)同步或者異步。如果采用異步模式,那么,備機(jī)房的數(shù)據(jù)總是落后于主機(jī)房。當(dāng)主機(jī)房整體出現(xiàn)故障時(shí),有兩種選擇:要么將服務(wù)切換到備機(jī)房,忍受數(shù)據(jù)丟失的風(fēng)險(xiǎn);要么停止服務(wù),直到主機(jī)房恢復(fù)為止。因此,如果數(shù)據(jù)同步為異步,那么,主備機(jī)房切換往往是手工的,允許用戶根據(jù)業(yè)務(wù)的特點(diǎn)選擇“丟失數(shù)據(jù)”或者“停止服務(wù)”。
如果采用強(qiáng)同步模式,那么,備機(jī)房的數(shù)據(jù)和主機(jī)房保持一致。當(dāng)主機(jī)房出現(xiàn)故障時(shí),除了手工切換,還可以采用自動(dòng)切換的方式,即通過分布式鎖服務(wù)檢測(cè)主機(jī)房的服務(wù),當(dāng)主機(jī)房出現(xiàn)故障時(shí),自動(dòng)將備機(jī)房切換為主機(jī)房。
B 、單個(gè)集群跨機(jī)房
將單個(gè)集群部署到多個(gè)機(jī)房,允許不同數(shù)據(jù)分片的主副本位于不同的機(jī)房,如圖 3-11 所示。每個(gè)數(shù)據(jù)分片在機(jī)房 1 和機(jī)房 2 ,總共包含 4 個(gè)副本,其中 A1 、 B1 、 C1 是主副本, A1 和 B1 在機(jī)房 1 , C1 在機(jī)房 2 。整個(gè)集群只有一個(gè)總控節(jié)點(diǎn),它需要同機(jī)房 1 和機(jī)房 2 的所有工作節(jié)點(diǎn)保持通信。當(dāng)總控節(jié)點(diǎn)出現(xiàn)故障時(shí),分布式鎖服務(wù)將檢測(cè)到,并將機(jī)房 2 的備份節(jié)點(diǎn)切換為總控節(jié)點(diǎn)。
如果采用這種部署方式,總控節(jié)點(diǎn)在執(zhí)行數(shù)據(jù)分布時(shí),需要考慮機(jī)房信息,也就是說,盡量將同一個(gè)數(shù)據(jù)分片的多個(gè)副本分布到多個(gè)機(jī)房,從而防止單個(gè)機(jī)房出現(xiàn)故障而影響正常服務(wù)。
C 、 Paxos 選主副本
如果采用 Paxos 協(xié)議選主副本,那么,每個(gè)數(shù)據(jù)分片的多個(gè)副本構(gòu)成一個(gè) Paxos 復(fù)制組。如圖所示, B1 、 B2 、 B3 、 B4 構(gòu)成一個(gè)復(fù)制組,某一時(shí)刻 B1 為復(fù)制組的主副本,當(dāng) B1 出現(xiàn)故障時(shí),其他副本將嘗試切換為主副本, Paxos 協(xié)議保證只有一個(gè)副本會(huì)成功。這樣,總控節(jié)點(diǎn)與工作節(jié)點(diǎn)之間不再需要保持租約,總控節(jié)點(diǎn)出現(xiàn)故障也不會(huì)對(duì)工作節(jié)點(diǎn)產(chǎn)生影響。它的優(yōu)點(diǎn)在于能夠降低對(duì)總控節(jié)點(diǎn)的依賴,缺點(diǎn)在于工程復(fù)雜度太高,很難在線下模擬所有的異常情況。
四、分布式文件系統(tǒng)
分布式文件系統(tǒng)的主要功能有兩個(gè):一個(gè)是存儲(chǔ)文檔、圖像、視頻之類的 Blob 類型數(shù)據(jù);另外一個(gè)是作為分布式表格系統(tǒng)的持久化層。
1、 Google 文件系統(tǒng)( GFS )
GFS, Big Table, Map Reduce 稱為 Google 的三駕馬車,是許多基礎(chǔ)服務(wù)的基石。
GFS 于 2003 年提出,是一個(gè)分布式的文件系統(tǒng),與此前的很多分布式系統(tǒng)的前提假設(shè)存在很大的不同,適用于以下場(chǎng)景
( 1 )認(rèn)為組件失效是一種常態(tài),提供了容錯(cuò)機(jī)制,自動(dòng)負(fù)載均衡,使得分布式文件系統(tǒng)可以在廉價(jià)機(jī)器上運(yùn)行;
( 2 )面向大文件存儲(chǔ),系統(tǒng)主要的工作負(fù)載是大規(guī)模的流式讀取,寫操作主要是追加方式寫,很少有隨機(jī)寫;
( 3 )一次寫入,多次讀取,例如互聯(lián)網(wǎng)上的網(wǎng)頁(yè)存儲(chǔ)
GFS 文件被劃分為固定大小的數(shù)據(jù)塊( chunk ),由主服務(wù)器在創(chuàng)建時(shí)分配一個(gè) 64 位全局唯一的 chunk 句柄。CS 以普通的 Linux 文件的形式將 chunk 存儲(chǔ)在磁盤中。為了保證可靠性, chunk 在不同的機(jī)器中復(fù)制多份,默認(rèn)為三份。
主控服務(wù)器中維護(hù)了系統(tǒng)的元數(shù)據(jù),包括文件及 chunk 命名空間、文件到 chunk 之間的映射、 chunk 位置信息。它也負(fù)責(zé)整個(gè)系統(tǒng)的全局控制,如 chunk 租約管理、垃圾回收無用 chunk 、 chunk 復(fù)制等。主控服務(wù)器會(huì)定期與 CS 通過心跳的方式交換信息。
客戶端是 GFS 提供給應(yīng)用程序的訪問接口,它是一組專用接口,不遵循 POSIX 規(guī)范,以庫(kù)文件的形式提供??蛻舳嗽L問 GFS 時(shí),首先訪問主控服務(wù)器節(jié)點(diǎn),獲取與之進(jìn)行交互的 CS 信息,然后直接訪問這些 CS ,完成數(shù)據(jù)存取工作。
需要注意的是, GFS 中的客戶端不緩存文件數(shù)據(jù),只緩存主控服務(wù)器中獲取的元數(shù)據(jù),這是由 GFS 的應(yīng)用特點(diǎn)決定的。GFS 最主要的應(yīng)用有兩個(gè):MapReduce 與 Bigtable 。對(duì)于 MapReduce,GFS 客戶端使用方式為順序讀寫,沒有緩存文件數(shù)據(jù)的必要;而 Bigtable 作為分布式表格系統(tǒng),內(nèi)部實(shí)現(xiàn)了一套緩存機(jī)制。另外,如何維護(hù)客戶端緩存與實(shí)際數(shù)據(jù)之間的一致性是一個(gè)極其復(fù)雜的問題。
由此可見, Hadoop 的 HDFS 其實(shí)是 GFS 的簡(jiǎn)化版,是 Cutting 博士“山寨” GFS 出來的產(chǎn)物。是盜火種的產(chǎn)物。
2、 Taobao 文件系統(tǒng)( TFS )
互聯(lián)網(wǎng)應(yīng)用經(jīng)常需要存儲(chǔ)用戶上傳的文檔、圖片、視頻等,比如 Facebook 相冊(cè)、淘寶圖片、 Dropbox 文檔等。文檔、圖片、視頻一般稱為 Blob 數(shù)據(jù)。Blob 文件系統(tǒng)的特點(diǎn)是數(shù)據(jù)寫入后基本都是只讀,很少出現(xiàn)更新操作,這就是 Taobao 文件系統(tǒng)( TFS )的主要特點(diǎn)。
TFS 架構(gòu)上借鑒了 GFS ,但與 GFS 又有很大的不同。
(1) TFS 內(nèi)部不維護(hù)文件目錄樹,扁平化的數(shù)據(jù)組織結(jié)構(gòu),可將文件名映射到文件的物理地址,簡(jiǎn)化了文件的訪問流程;
(2) 針對(duì)海量小文件的隨機(jī)讀寫訪問性能做了特殊優(yōu)化,滿足了淘寶對(duì)小文件存儲(chǔ)的需求,被廣泛地應(yīng)用在淘寶各項(xiàng)應(yīng)用中;
(3) 采用了 HA 架構(gòu)和平滑擴(kuò)容,保證了整個(gè)文件系統(tǒng)的可用性和擴(kuò)展性。
一個(gè) TFS 集群由兩個(gè) NameServer 節(jié)點(diǎn)(一主一備)和多個(gè) DataServer 節(jié)點(diǎn)組成, NameServer 通過心跳對(duì) DataSrver 的狀態(tài)進(jìn)行監(jiān)測(cè)。NameServer 相當(dāng)于 GFS 中的 Master,DataServer 相當(dāng)于 GFS 中的 ChunkServer 。NameServer 區(qū)分為主 NameServer 和備 NameServer ,只有主 NameServer 提供服務(wù),當(dāng)主 NameServer 出現(xiàn)故障時(shí),能夠被心跳守護(hù)進(jìn)程檢測(cè)到,并將服務(wù)切換到備 NameServer 。每個(gè) DataServer 上會(huì)運(yùn)行多個(gè) dsp 進(jìn)程,一個(gè) dsp 對(duì)應(yīng)一個(gè)掛載點(diǎn),這個(gè)掛載點(diǎn)一般對(duì)應(yīng)一個(gè)獨(dú)立磁盤,從而管理多塊磁盤。
在 TFS 中,將大量的小文件(實(shí)際數(shù)據(jù)文件)合并成一個(gè)大文件(這一點(diǎn)比 HDFS 有優(yōu)化和改進(jìn)),這個(gè)大文件稱為塊( Block ),每個(gè) Block 擁有在集群內(nèi)唯一的編號(hào)(塊 ID ),通過<塊 ID ,塊內(nèi)偏移>可以唯一確定一個(gè)文件。TFS 中 Block 的實(shí)際數(shù)據(jù)都存儲(chǔ)在 DataServer 中,大小一般為 64MB ,默認(rèn)存儲(chǔ)三份,相當(dāng)于 GFS 中的 chunk 。應(yīng)用客戶端是 TFS 提供給應(yīng)用程序的訪問接口,應(yīng)用客戶端不緩存文件數(shù)據(jù),只緩存 NameServer 的元數(shù)據(jù)。
3、 Fackbook Haystack 文件系統(tǒng)
到 2014 年, Facebook 大概有超 4000 億張圖片,總大小為 30PB ,通過計(jì)算可以得出每張照片的平均大小為 30PB/260GB ,約為 100KB 。用戶每周新增照片數(shù)為 10 億(總大小為 60TB ),平均每秒新增的照片數(shù)為 109/7/40000 (按每天 40000s 計(jì)),約為每秒 3800 次寫操作,讀操作峰值可以達(dá)到每秒百萬次。
Facebook 相冊(cè)后端早期采用基于 NAS 的存儲(chǔ),通過 NFS 掛載 NAS 中的照片文件來提供服務(wù)。后來出于性能和成本考慮,自主研發(fā)了 Facebook Haystack 存儲(chǔ)相冊(cè)數(shù)據(jù)。
和 TFS 類似, Facebook Haystack 新架構(gòu)主要解決圖片存取 IO 次數(shù)過多的文件,主要的思路是多個(gè)邏輯文件共享同一個(gè)物理文件。Haystack 架構(gòu)及讀請(qǐng)求處理流程圖如下
Haystack 架構(gòu)主要有三個(gè)部分:Haystack Directory , Haystack Store 以及 Haystack Cache 。Haystack Store 是物理存儲(chǔ)節(jié)點(diǎn),以物理卷軸 (physical volume) 的形式組織存儲(chǔ)空間,每個(gè)物理卷軸一般很大,比如 100GB ,這樣 10TB 的數(shù)據(jù)也只有 100 個(gè)物理卷軸。每個(gè)物理卷軸對(duì)應(yīng)一個(gè)物理文件,因此,每個(gè)存儲(chǔ)節(jié)點(diǎn)上的物理文件元信息都很小。多個(gè)物理存儲(chǔ)節(jié)點(diǎn)上的物理卷軸組成一個(gè)邏輯卷軸 (logical volume) ,用于備份。Haystack Directory 存放邏輯卷軸和物理卷軸的對(duì)應(yīng)關(guān)系,假設(shè)每個(gè)卷軸的大小為 100GB ,對(duì)應(yīng)關(guān)系的條數(shù)為 20PB / 100GB = 0.2MB ,占用的內(nèi)存可以忽略。Haystack cache 主要用于解決對(duì) CDN 提供商過于依賴的問題,提供最近增加的圖片的緩存服務(wù)。
Haystack 圖片讀取請(qǐng)求大致流程為:用戶訪問一個(gè)頁(yè)面時(shí), Web Server 請(qǐng)求 Haystack Directory 構(gòu)造一個(gè) URL :http:// < CDN > / < Cache > / < Machine id > / < Logical volume,Photo > ,后續(xù)根據(jù)各個(gè)部分的信息依次訪問 CDN , Cache 和后端的 Haystack Store 存儲(chǔ)節(jié)點(diǎn)。Haystack Directory 構(gòu)造 URL 時(shí)可以省略 部分從而使得用戶直接請(qǐng)求 Haystack Cache 而不必經(jīng)過 CDN 。Haystack cache 收到的請(qǐng)求包含兩個(gè)部分:用戶 Browser 的請(qǐng)求及 CDN 的請(qǐng)求, Haystack cache 只緩存用戶 Browser 發(fā)送的請(qǐng)求且要求請(qǐng)求的 Haystack Store 存儲(chǔ)節(jié)點(diǎn)是可寫的。一般來說, Haystack Store 的存儲(chǔ)節(jié)點(diǎn)寫一段時(shí)間以后達(dá)到容量上限變?yōu)橹蛔x,因此,可寫節(jié)點(diǎn)的圖片為最近增加的圖片,是熱點(diǎn)數(shù)據(jù)。
Haystack 的寫請(qǐng)求 ( 圖片上傳 ) 處理流程為:Web Server 首先請(qǐng)求 Haystack Directory 獲取圖片的 id 和可寫的邏輯卷軸,接著將數(shù)據(jù)寫入對(duì)應(yīng)的每一個(gè)物理卷軸 ( 備份數(shù)一般為 3) 。
Facebook Haystack 及 Taobao TFS 這樣的文件系統(tǒng)一般稱為 Blob 文件系統(tǒng)。它們都是解決大量的小圖片文件的問題,因此架構(gòu)很類似,不同點(diǎn)包括
(1) 邏輯卷軸大小的選擇,比如 Haystack 選擇 100GB 的邏輯卷軸大小, TFS 中 block 大小一般為 64MB ;
(2) Haystack 使用 RAID 6 ,且底層文件系統(tǒng)使用性能更好的 XFS ,淘寶后期擯除了 RAID 機(jī)制,文件系統(tǒng)使用 Ext3 ;
(3) Haystack 使用了 Akamai & Limelight 的 CDN 服務(wù),而 Taobao 已經(jīng)使用自建的 CDN ,當(dāng)然, Facebook 也在考慮自建 CDN 。
4、 CDN 內(nèi)容分發(fā)網(wǎng)絡(luò)
CDN 的全稱是 Content Delivery Network ,即內(nèi)容分發(fā)網(wǎng)絡(luò)。其目的是通過在現(xiàn)有的 Internet 中增加一層新的網(wǎng)絡(luò)架構(gòu),將網(wǎng)站的內(nèi)容發(fā)布到最接近用戶的網(wǎng)絡(luò) " 邊緣 " 。實(shí)現(xiàn)如下三個(gè)目的
( 1 )解決因分布、帶寬、服務(wù)器性能帶來的訪問延遲問題,適用于站點(diǎn)加速、點(diǎn)播、直播等場(chǎng)景。使用戶可就近取得所需內(nèi)容,解決 Internet 網(wǎng)絡(luò)擁擠的狀況,提高用戶訪問網(wǎng)站的響應(yīng)速度和成功率。
( 2 )控制時(shí)延無疑是現(xiàn)代信息科技的重要指標(biāo), CDN 的意圖就是盡可能的減少資源在轉(zhuǎn)發(fā)、傳輸、鏈路抖動(dòng)等情況下順利保障信息的連貫性。
( 3 ) CDN 就是扮演者護(hù)航者和加速者的角色,更快準(zhǔn)狠的觸發(fā)信息和觸達(dá)每一個(gè)用戶,帶來更為極致的使用體驗(yàn)。
如下圖所示 DNS 在對(duì)域名解析時(shí)不再向用戶返回源服務(wù)器的 IP ,而是返回了由智 CDN 負(fù)載均衡系統(tǒng)選定的某個(gè)邊緣節(jié)點(diǎn)的 IP 。用戶利用這個(gè) IP 訪問邊緣節(jié)點(diǎn),然后該節(jié)點(diǎn)通過其內(nèi)部 DNS 解析得到源服務(wù)器 IP 并發(fā)出請(qǐng)求來獲取用戶所需的頁(yè)面,如果請(qǐng)求成功,邊緣節(jié)點(diǎn)會(huì)將頁(yè)面緩存下來,下次用戶訪問時(shí)可以直接讀取,而不需要每次都訪問源服務(wù)器。
Taobao 的 CDN 架構(gòu)是自研的,用于支持用戶購(gòu)物,尤其是“雙 11” 光棍節(jié)時(shí)的海量圖片請(qǐng)求,圖片存儲(chǔ)在后臺(tái)的 TFS 集群中, CDN 系統(tǒng)將這些圖片緩存到離用戶最近的邊緣節(jié)點(diǎn)。CDN 采用兩級(jí) Cache :L1-Cache 以及 L2-Cache 。用戶訪問淘寶網(wǎng)的圖片時(shí),通過全局調(diào)度系統(tǒng)( Global Load Balancing )調(diào)度到某個(gè) L1-Cache 節(jié)點(diǎn)。如果 L1-Cache 命中,那么直接將圖片數(shù)據(jù)返回用戶;否則,請(qǐng)求 L2-Cache 節(jié)點(diǎn),并將返回的圖片數(shù)據(jù)緩存到 L1-Cache 節(jié)點(diǎn)。如果 L2-Cache 命中,直接將圖片數(shù)據(jù)返回給 L1-Cache 節(jié)點(diǎn);否則,請(qǐng)求源服務(wù)器的圖片服務(wù)器集群。每臺(tái)圖片服務(wù)器是一個(gè)運(yùn)行著 Nginx 的 Web 服務(wù)器,它還會(huì)在本地緩存圖片,只有當(dāng)本地緩存也不命中時(shí)才會(huì)請(qǐng)求后端的 TFS 集群,圖片服務(wù)器集群和 TFS 集群部署在同一個(gè)數(shù)據(jù)中心內(nèi)。
對(duì)于每個(gè) CDN 節(jié)點(diǎn),其架構(gòu)如圖 4-11 所示。從圖中可以看出,每個(gè) CDN 節(jié)點(diǎn)內(nèi)部通過 LVS+Haproxy 的方式進(jìn)行負(fù)載均衡。其中, LVS 是四層負(fù)載均衡軟件,性能好;Haproxy 是七層負(fù)載均衡軟件,能夠支持更加靈活的負(fù)載均衡策略。通過有機(jī)結(jié)合兩者,可以將不同的圖片請(qǐng)求調(diào)度到不同的 Squid 服務(wù)器。
上圖是 CDN 的單節(jié)點(diǎn)架構(gòu),它有以下三個(gè)特點(diǎn)
(1) Squid 服務(wù)器構(gòu)成淘寶單節(jié)點(diǎn)中的 CDN 中的分布式緩存,這個(gè)實(shí)現(xiàn)比分布式緩存簡(jiǎn)單很多,因?yàn)椴恍枰紤]數(shù)據(jù)持久化。
(2) 分級(jí)緩存,由于緩存數(shù)據(jù)有較高的局部性,在 Squid 服務(wù)器上使用 SSD+SAS+SATA 混合存儲(chǔ),圖片隨著熱點(diǎn)變化而遷移,最熱門的存儲(chǔ)到 SSD ,中等熱度的存儲(chǔ)到 SAS ,輕熱度的存儲(chǔ)到 SATA 。通過這樣的方式,能夠很好地結(jié)合 SSD 的性能和 SAS 、 SATA 磁盤的成本優(yōu)勢(shì);
(3) 低功耗服務(wù)器定制, CDN 緩存服務(wù)是 IO 密集型而不是 CPU 密集型的服務(wù),因此,選用 Intel Atom CPU 定制低功耗服務(wù)器,在保證服務(wù)性能的前提下大大降低了整體功耗。
五、分布式鍵值系統(tǒng)
分布式鍵值系統(tǒng)是用于存儲(chǔ)關(guān)系簡(jiǎn)單的半結(jié)構(gòu)化數(shù)據(jù),半結(jié)構(gòu)化數(shù)據(jù)均封裝成由 鍵值對(duì)組成的對(duì)象,其中 key 為唯一標(biāo)示符;value 為屬性值,可以為任何類型,如文字、圖片,也可以為空;timestamp 為時(shí)間戳,提供對(duì)象的多版本支持。分布式鍵值系統(tǒng)以鍵值對(duì)存儲(chǔ),它的結(jié)構(gòu)不固定,每一元組可以有不一樣的字段,可根據(jù)需要增加鍵值對(duì),從而不局限于固定的結(jié)構(gòu),適用面更大,可擴(kuò)展性更好。
分布式鍵值系統(tǒng)支持針對(duì)單個(gè) 鍵值對(duì)的增、刪、查、改操作,可以運(yùn)行在 PC 服務(wù)器集群上,并實(shí)現(xiàn)集群按需擴(kuò)展,從而處理大規(guī)模數(shù)據(jù),并通過數(shù)據(jù)備份保障容錯(cuò)性,避免了分割數(shù)據(jù)帶來的復(fù)雜性和成本。
總體來說,分布式鍵值系統(tǒng)從存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)的角度看,分布式鍵值系統(tǒng)與傳統(tǒng)的哈希表比較類似,不同的是,分布式鍵值系統(tǒng)支持將數(shù)據(jù)分布到集群中的多個(gè)存儲(chǔ)節(jié)點(diǎn)。分布式鍵值系統(tǒng)可以配置數(shù)據(jù)的備份數(shù)目,可以將一份數(shù)據(jù)的所有副本存儲(chǔ)到不同的節(jié)點(diǎn)上,當(dāng)有節(jié)點(diǎn)發(fā)生異常無法正常提供服務(wù)時(shí),其余的節(jié)點(diǎn)會(huì)繼續(xù)提供服務(wù)。
1、 Amazon Dynamo
Dynamo 以很簡(jiǎn)單的鍵值方式存儲(chǔ)數(shù)據(jù),不支持復(fù)雜的查詢。Dynamo 中存儲(chǔ)的是數(shù)據(jù)值的原始形式,不解析數(shù)據(jù)的具體內(nèi)容。Dynamo 主要用于 Amazon 的購(gòu)物車及 S3 云存儲(chǔ)服務(wù)。在實(shí)現(xiàn)過程中解決了如下問題:


咨詢
建站咨詢
