偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

開(kāi)發(fā) 架構(gòu) 分布式
設(shè)計(jì)有效的系統(tǒng)來(lái)進(jìn)行快速的大數(shù)據(jù)訪問(wèn)是有趣的,同時(shí)有大量的好工具來(lái)幫助各種各樣的應(yīng)用程序進(jìn)行設(shè)計(jì)。 這文章只覆蓋了一些例子,僅僅是一些表面的東西,但將會(huì)越來(lái)越多–同時(shí)在這個(gè)領(lǐng)域里一定會(huì)繼續(xù)有更多創(chuàng)新東西。

開(kāi)放源代碼已經(jīng)成為一些大型網(wǎng)站的基本原則。而在這些網(wǎng)站成長(zhǎng)的過(guò)程中,一些優(yōu)秀的實(shí)踐經(jīng)驗(yàn)和規(guī)則也出現(xiàn)在他們的結(jié)構(gòu)中。本文旨在介紹一些在大型網(wǎng)站結(jié)構(gòu)設(shè)計(jì)的過(guò)程中需要注意的關(guān)鍵問(wèn)題以及實(shí)現(xiàn)目標(biāo)的基礎(chǔ)工作。

本文側(cè)重于介紹網(wǎng)絡(luò)系統(tǒng),盡管一些準(zhǔn)則在其他分布式系統(tǒng)中也是適用的。

1.1. web分布式系統(tǒng)的設(shè)計(jì)原則

搭建和運(yùn)營(yíng)一個(gè)可伸縮的web站點(diǎn)或者應(yīng)用程序意味著什么?在原始層面上這僅僅是用戶(hù)通過(guò)互聯(lián)網(wǎng)連接到遠(yuǎn)程資源-使系統(tǒng)變得可伸縮的部分是將資源、或者訪問(wèn)的資源,分布于多個(gè)服務(wù)器上。

像生活中大多數(shù)事情一樣,當(dāng)構(gòu)建一個(gè)web服務(wù)時(shí)花時(shí)間提前做好計(jì)劃從長(zhǎng)遠(yuǎn)看來(lái)還是很有幫助的;了解一些注意事項(xiàng)和大網(wǎng)站背后的權(quán)衡原則可以在創(chuàng)建小型網(wǎng)站時(shí)做出更明智的決定。以下是一些影響大規(guī)模web系統(tǒng)設(shè)計(jì)的關(guān)鍵原則:

  • 可用性:對(duì)于很多公司來(lái)說(shuō)一個(gè)網(wǎng)站的正常運(yùn)行時(shí)間是非常關(guān)鍵的聲譽(yù)和功能,像一些大型的在線零售系統(tǒng),即使一分鐘的宕機(jī)都有可能導(dǎo)致數(shù)千或者數(shù)百萬(wàn)美元的損失,因此設(shè)計(jì)系統(tǒng)的時(shí)時(shí)可用性和彈性的錯(cuò)誤處理機(jī)制既是一個(gè)基本業(yè)務(wù)也是一個(gè)技術(shù)要求。 高可用分布式系統(tǒng)需要仔細(xì)考慮關(guān)鍵組件的冗余,分系統(tǒng)失敗后能快速修復(fù),并且當(dāng)問(wèn)題出現(xiàn)時(shí)優(yōu)雅型降級(jí)。
  • 性能:網(wǎng)站的性能正在變成大多數(shù)站點(diǎn)考慮的一個(gè)重要的方面,網(wǎng)站的速度影響正常使用和用戶(hù)的滿(mǎn)意度,同樣影響搜索的排名,這也是影響網(wǎng)站收益和保留用戶(hù)的一個(gè)因素。因此,創(chuàng)建一個(gè)快速響應(yīng)和低延遲的系統(tǒng)是非常關(guān)鍵的。
  • 可靠性:一個(gè)系統(tǒng)需要具備可靠性,比如同一個(gè)數(shù)據(jù)的請(qǐng)求始終返回同樣的數(shù)據(jù)響應(yīng) 。如果數(shù)據(jù)改變或者被更新,那么同樣的數(shù)據(jù)將返回一個(gè)新的數(shù)據(jù)。用戶(hù)需要知道一些東西被寫(xiě)入系統(tǒng)或者被存儲(chǔ)到系統(tǒng)后,系統(tǒng)會(huì)保持不變并且可以在以后恢復(fù)到合適的位置。
  • 可伸縮性:當(dāng)談到任何大型的分布式系統(tǒng)時(shí),規(guī)模大小只是考慮的其中一個(gè)方面,同樣重要的是增強(qiáng)處理較大規(guī)模的負(fù)載性能所做的努力,這通常稱(chēng)為系統(tǒng)的可伸縮性??缮炜s性可以代表系統(tǒng)很多不同的參數(shù):額外流量的處理量,添加存儲(chǔ)容量的便意性,甚至事務(wù)的處理量。
  • 可管理性: 設(shè)計(jì)一個(gè)系統(tǒng)可以方便操作是另一個(gè)重要的考慮方面,系統(tǒng)的可管理性等同于操作的可伸縮性:維護(hù)和升級(jí)??晒芾硇孕枰紤]的事情是當(dāng)問(wèn)題發(fā)生時(shí)方便診斷和了解問(wèn)題,易于升級(jí)和修改,以及系統(tǒng)能簡(jiǎn)單性的操作(即,例行的操作有沒(méi)有失敗和異常?)
  • 成本: 成本是一個(gè)重要的因素。很明顯這包含硬件和軟件成本,但同樣重要需要考慮的其他方面是部署和維護(hù)系統(tǒng)的成本。開(kāi)發(fā)者構(gòu)建系統(tǒng)花費(fèi)的大量時(shí)間,運(yùn)維部署時(shí)間,甚至培訓(xùn)時(shí)間都需要考慮,成本是總體成本。

以上每個(gè)原則都為設(shè)計(jì)分布式web架構(gòu)提供了基礎(chǔ)決策。然而,他們也能彼此互斥,例如要實(shí)現(xiàn)某個(gè)目標(biāo)就要以另外的作為代價(jià)。一個(gè)基本的例子:選擇通過(guò)單純?cè)黾痈嗟姆?wù)器(可擴(kuò)展性)來(lái)增加地址容量,是以可管理性(你必須操作增加的服務(wù)器)和成本(服務(wù)器的價(jià)格)為代價(jià)的。

當(dāng)設(shè)計(jì)任何的web應(yīng)用程序時(shí),考慮這些關(guān)鍵原則都是很重要的,即使得承認(rèn)一個(gè)設(shè)計(jì)可能要犧牲它們之中的一個(gè)或者多個(gè)。

1.2. 基礎(chǔ)

當(dāng)設(shè)計(jì)一個(gè)系統(tǒng)架構(gòu)時(shí),有一些東西是要考慮的:正確的部分是什么,怎樣讓這些部分很好地融合在一起,以及好的折中方法是什么。通常在系統(tǒng)架構(gòu)需要之前就為它的可擴(kuò)展性投資不是一個(gè)聰明的商業(yè)抉擇;然而,在設(shè)計(jì)上的深謀遠(yuǎn)慮能在未來(lái)節(jié)省大量的時(shí)間和資源。

這部分關(guān)注點(diǎn)是幾乎所有大型web應(yīng)用程序中心的一些核心因素:服務(wù)、冗余、劃分和錯(cuò)誤處理。每一個(gè)因素都包含了選擇和妥協(xié),特別是上部分提到的設(shè)計(jì)原則。為了詳細(xì)的解析這些,最好是用一個(gè)例子來(lái)開(kāi)始。

實(shí)例:圖片托管應(yīng)用

有時(shí)候你可能會(huì)在線上傳一張圖片。對(duì)于那些托管并負(fù)責(zé)分發(fā)大量圖片的網(wǎng)站來(lái)說(shuō),要搭建一個(gè)既節(jié)省成本又高效還能具備較低的延遲性(你能快速的獲圖片)的網(wǎng)站架構(gòu)確實(shí)是一種挑戰(zhàn)。

我們來(lái)假設(shè)一個(gè)系統(tǒng),用戶(hù)可以上傳他們的圖片到中心服務(wù)器,這些圖片又能夠讓一些web鏈接或者API獲取這些圖片,就如同現(xiàn)在的Flickr或者 Picasa。為了簡(jiǎn)化的需要,我們假設(shè)應(yīng)用程序分為兩個(gè)主要的部分:一個(gè)是上傳圖片到服務(wù)器的能力(通常說(shuō)的寫(xiě)操作),另一個(gè)是查詢(xún)一個(gè)圖片的能力。然而,我們當(dāng)然想上傳功能很高效,但是我們更關(guān)心的是能夠快速分發(fā)能力,也就是說(shuō)當(dāng)某個(gè)人請(qǐng)求一個(gè)圖片的時(shí)候(比如,一個(gè)web頁(yè)面或者其它應(yīng)用程序請(qǐng)求圖片)能夠快速的滿(mǎn)足。這種分發(fā)能力很像web服務(wù)器或者CDN連接服務(wù)器(CDN服務(wù)器一般用來(lái)在多個(gè)位置存儲(chǔ)內(nèi)容一邊這些內(nèi)容能夠從地理位置或者物理上更靠近訪問(wèn)它的用戶(hù),已達(dá)到高效訪問(wèn)的目的)氣的作用。

系統(tǒng)其他重要方面:

  • 對(duì)圖片存儲(chǔ)的數(shù)量沒(méi)有限制,所以存儲(chǔ)需要可擴(kuò)展,在圖像數(shù)量方面需要考慮。
  • 圖片的下載和請(qǐng)求不需要低延遲。
  • 如果用戶(hù)上傳一個(gè)圖片,圖片應(yīng)該都在那里(圖片數(shù)據(jù)的可靠性)。
  • 系統(tǒng)應(yīng)該容易管理(可管理性)。
  • 由于圖片主機(jī)不會(huì)有高利潤(rùn)的空間,所以系統(tǒng)需要具有成本效益。

Figure 1.1是一個(gè)簡(jiǎn)化的功能圖。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.1: 圖片主機(jī)應(yīng)用的簡(jiǎn)化架構(gòu)圖

在這個(gè)圖片主機(jī)的例子里,可遇見(jiàn)系統(tǒng)必需快速,它的數(shù)據(jù)存儲(chǔ)要可靠以及這些所有的屬性都應(yīng)該高度的可擴(kuò)展。建立這個(gè)應(yīng)用程序的一個(gè)小版本不是很重要而且很容易部署在單一的服務(wù)器上;然而,這不是這節(jié)里的感興趣部分。假設(shè)下我們想建一個(gè)會(huì)增長(zhǎng)到和Flickr痛讓規(guī)模的東西。

#p#

服務(wù)

當(dāng)要考慮設(shè)計(jì)一個(gè)可擴(kuò)展的系統(tǒng)時(shí),為功能解耦和考慮下系統(tǒng)每部分的服務(wù)都定義一個(gè)清晰的接口都是很有幫助的。在實(shí)際中,在這種方式下的系統(tǒng)設(shè)計(jì)被成為面向服務(wù)架構(gòu)(SOA)。對(duì)于這類(lèi)型的系統(tǒng),每個(gè)服務(wù)有自己獨(dú)立的方法上下文,以及使用抽象接口與上下文的外部任何東西進(jìn)行交互,典型的是別的服務(wù)的公共API。

把一個(gè)系統(tǒng)解構(gòu)為一些列互補(bǔ)的服務(wù),能夠?yàn)檫@些部分從別的部分的操作解耦。這樣的抽象幫助在這些服務(wù)服、它的基礎(chǔ)環(huán)境和服務(wù)的消費(fèi)者之間建立清晰的關(guān)系。建立這種清晰的輪廓能幫助隔離問(wèn)題,但也允許各模塊相對(duì)其它部分獨(dú)立擴(kuò)展。這類(lèi)面向服務(wù)設(shè)計(jì)系統(tǒng)是非常類(lèi)似面向?qū)ο笤O(shè)計(jì)編程的。

在我們的例子中,上傳和檢索圖像的請(qǐng)求都是由同一個(gè)服務(wù)器處理的;然而,因?yàn)橄到y(tǒng)需要具有伸縮性,有理由要將這兩個(gè)功能分解為各由自己的服務(wù)進(jìn)行處理。

快速轉(zhuǎn)發(fā)(Fast-forward)假定服務(wù)處于大量使用中;在這種情況下就很容易看到,讀取圖像所花的時(shí)間中有多少是由于受到了寫(xiě)入操作的影響(因?yàn)檫@兩個(gè)功能將競(jìng)爭(zhēng)使用它們共享的資源)。取決于所采用的體系結(jié)構(gòu),這種影響可能是巨大的。即使上傳和下載的速度完全相同(在絕大多數(shù)IP網(wǎng)絡(luò)中都不是這樣的情況,大部分下載速度和上傳速度之比都至少設(shè)計(jì)為3:1),文件讀取操作一般都是從高速緩存中進(jìn)行的,而寫(xiě)操作卻不得不進(jìn)行最終的磁盤(pán)操作(而且可能要寫(xiě)幾次才能達(dá)成最后的一致?tīng)顟B(tài))。即使所有內(nèi)容都已在內(nèi)存中,或者從磁盤(pán)(比如SSD磁盤(pán))中進(jìn)行讀取,數(shù)據(jù)庫(kù)寫(xiě)入操作幾乎往往都要慢于讀取操作。(Pole Position是一個(gè)開(kāi)源的DB基準(zhǔn)測(cè)試工具,http://polepos.org/,測(cè)試結(jié)果參見(jiàn) http://polepos.sourceforge.net/results/PolePositionClientServer.pdf

這種設(shè)計(jì)另一個(gè)潛在的問(wèn)題出在web服務(wù)器上,像Apache或者lighttpd通常都有一個(gè)能夠維持的并發(fā)連接數(shù)上限(默認(rèn)情況下在500左右,不過(guò)可以更高)和最高流量數(shù),它們會(huì)很快被寫(xiě)操作消耗掉。因?yàn)樽x操作可以異步進(jìn)行,或者采用其它一些像gizp壓縮的性能優(yōu)化或者塊傳輸編碼方式,web服務(wù)器可以通過(guò)在多個(gè)請(qǐng)求服務(wù)之間切換來(lái)滿(mǎn)足比最大連接數(shù)更多的請(qǐng)求(一臺(tái)Apache的最大連接數(shù)設(shè)置為500,它每秒鐘提供近千次讀請(qǐng)求服務(wù)也是正常的)。寫(xiě)操作則不同,它需要在上傳過(guò)程中保持連接,所以大多數(shù)家庭網(wǎng)絡(luò)環(huán)境下,上傳一個(gè)1MB的文件可能需要超過(guò)1秒的時(shí)間,所以web服務(wù)器只能處理500個(gè)這樣并發(fā)寫(xiě)操作請(qǐng)求。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

對(duì)于這種瓶頸,一個(gè)好的規(guī)劃案例是將讀取和寫(xiě)入圖片分離為兩個(gè)獨(dú)立的服務(wù),如圖Figure 1.2.所示。這讓我們可以單獨(dú)的擴(kuò)展其中任意一個(gè)(因?yàn)橛锌赡芪覀冏x操作比寫(xiě)操作要頻繁很多),同時(shí)也有助于我們理清每個(gè)節(jié)點(diǎn)在做什么。最后,這也避免了未來(lái)的憂慮,這使得故障診斷和查找問(wèn)題更簡(jiǎn)單,像慢讀問(wèn)題。

這種方法的優(yōu)點(diǎn)是我們能夠單獨(dú)的解決各個(gè)模塊的問(wèn)題-我們不用擔(dān)心寫(xiě)入和檢索新圖片在同一個(gè)上下文環(huán)境中。這兩種服務(wù)仍然使用全球資料庫(kù)的圖片,但是它們可通過(guò)適當(dāng)?shù)姆?wù)接口自由優(yōu)化它們自己的性能(比如,請(qǐng)求隊(duì)列,或者緩存熱點(diǎn)圖片-在這之上的優(yōu)化)。從維護(hù)和成本角度來(lái)看,每個(gè)服務(wù)按需進(jìn)行獨(dú)立規(guī)模的規(guī)劃,這點(diǎn)非常有用,試想如果它們都組合混雜在一起,其中一個(gè)無(wú)意間影響到了性能,另外的也會(huì)受影響。

當(dāng)然,上面的例子在你使用兩個(gè)不同端點(diǎn)時(shí)可以很好的工作(事實(shí)上,這非常類(lèi)似于云存儲(chǔ)和內(nèi)容分發(fā)網(wǎng)絡(luò))。雖然有很多方式來(lái)解決這樣的瓶頸,但每個(gè)都有各自的取舍。

比如,F(xiàn)lickr通過(guò)分配用戶(hù)訪問(wèn)不同的分片解決這類(lèi)讀/寫(xiě)問(wèn)題,每一個(gè)分片只可以處理一定數(shù)量的用戶(hù),隨著用戶(hù)的增加更多的分片被添加到集群上(參看“Flickr縮影”的描述http://mysqldba.blogspot.com/2008/04/mysql-uc-2007-presentation-file.html)。在第一個(gè)例子中,可以根據(jù)實(shí)際用途更簡(jiǎn)單的規(guī)劃硬件資源(在整個(gè)系統(tǒng)中讀和寫(xiě)的比例),然而,F(xiàn)lickr規(guī)劃是根據(jù)用戶(hù)基數(shù)(假定每個(gè)用戶(hù)擁有相同的資源空間)。在前者中一個(gè)故障或者問(wèn)題會(huì)導(dǎo)致整個(gè)系統(tǒng)功能的下降(比如,全部不能寫(xiě)入文件了),然而Flickr一個(gè)分片的故障只會(huì)影響到相關(guān)的那部分用戶(hù)。在第一個(gè)例子中,更容易操作整個(gè)數(shù)據(jù)集-比如,在所有的圖像元數(shù)據(jù)上更新寫(xiě)入服務(wù)用來(lái)包含新的元數(shù)據(jù)或者檢索-然而在Flickr架構(gòu)上每一個(gè)分片都需要執(zhí)行更新或者檢索(或者需要?jiǎng)?chuàng)建個(gè)索引服務(wù)來(lái)核對(duì)元數(shù)據(jù)-找出哪一個(gè)才是實(shí)際結(jié)果)。

冗余(Redundancy)

為了優(yōu)雅的處理故障,web架構(gòu)必須冗余它的服務(wù)和數(shù)據(jù)。例如,單服務(wù)器只擁有單文件的話,文件丟失就意味這永遠(yuǎn)丟失了。丟失數(shù)據(jù)是個(gè)很糟糕的事情,常見(jiàn)的方法是創(chuàng)建多個(gè)或者冗余備份。

同樣的原則也適用于服務(wù)。如果應(yīng)用有一個(gè)核心功能,確保它同時(shí)運(yùn)行多個(gè)備份或者版本可以安全的應(yīng)對(duì)單點(diǎn)故障。

在系統(tǒng)中創(chuàng)建冗余可以消除單點(diǎn)故障,可以在緊急時(shí)刻提供備用功能。例如,如果在一個(gè)產(chǎn)品中同時(shí)運(yùn)行服務(wù)的兩個(gè)實(shí)例,當(dāng)其中一個(gè)發(fā)生故障或者降級(jí)(degrade),系統(tǒng)可以轉(zhuǎn)移(failover)到好的那個(gè)備份上。故障轉(zhuǎn)移(Failover)可以自動(dòng)執(zhí)行或者人工手動(dòng)干預(yù)。

服務(wù)冗余的另一個(gè)關(guān)鍵部分是創(chuàng)建無(wú)共享(shared-nothing)架構(gòu)。采用這種架構(gòu),每個(gè)接點(diǎn)都可以獨(dú)立的運(yùn)作,沒(méi)有中心”大腦”管理狀態(tài)或者協(xié)調(diào)活動(dòng)。這可以大大提高可伸縮性(scalability)因?yàn)樾碌慕狱c(diǎn)可以隨時(shí)加入而不需要特殊的條件或者知識(shí)。而且更重要的是,系統(tǒng)沒(méi)有單點(diǎn)故障。所以可以更好的應(yīng)對(duì)故障。

例如,在我們的圖片服務(wù)應(yīng)用,所有的圖片應(yīng)該都冗余備份在另外的一個(gè)硬件上(理想的情況下,在不同的地理位置,以防數(shù)據(jù)中心發(fā)生大災(zāi)難,例如地震,火災(zāi)),而且訪問(wèn)圖片的服務(wù)(見(jiàn)Figure 1.3.)-包括所有潛在的服務(wù)請(qǐng)求-也應(yīng)該冗余。(負(fù)載均衡器是個(gè)很好的方法冗余服務(wù),但是下面的方法不僅僅是負(fù)載均衡)

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.3: 使用冗余的圖片存儲(chǔ)

#p#

分區(qū)

我們可能遇見(jiàn)單一服務(wù)器無(wú)法存放的龐大數(shù)據(jù)集。也可能遇到一個(gè)需要過(guò)多計(jì)算資源的操作,導(dǎo)致性能下降,急需增添容量。這些情況下,你都有兩種選擇:橫向或縱向擴(kuò)展。

縱向擴(kuò)展意味著對(duì)單一服務(wù)器增添更多資源。對(duì)于一個(gè)非常龐大的數(shù)據(jù)集,這可能意味著為單一服務(wù)器增加更多(或更大)的硬盤(pán)以存放整個(gè)數(shù)據(jù)集。而對(duì)于計(jì)算操作,這可能意味著將操作移到一個(gè)擁有更快的 CPU 或 更大的內(nèi)存的服務(wù)器中。無(wú)論哪種情況,縱向擴(kuò)展都是為了使單個(gè)服務(wù)器能夠自己處理更多的方法。

另一方面,對(duì)于橫向擴(kuò)展,則是增加更多的節(jié)點(diǎn)。例如龐大的數(shù)據(jù)集,你可以用第二個(gè)服務(wù)器來(lái)存放部分?jǐn)?shù)據(jù);而對(duì)于計(jì)算操作,你可以切割計(jì)算,或是通過(guò)額外的節(jié)點(diǎn)加載。想要充分的利用橫向擴(kuò)展的優(yōu)勢(shì),你應(yīng)該以?xún)?nèi)在的系統(tǒng)構(gòu)架設(shè)計(jì)原則來(lái)實(shí)現(xiàn),否則的話,實(shí)現(xiàn)的方法將會(huì)變成繁瑣的修改和切分操作。

說(shuō)道橫向分區(qū),更常見(jiàn)的技術(shù)是將你的服務(wù)分區(qū),或分片。分區(qū)可以通過(guò)對(duì)每個(gè)功能邏輯集的分割分配而來(lái);可以通過(guò)地域劃分,也可以通過(guò)類(lèi)似付費(fèi) vs. 未付費(fèi)用戶(hù)來(lái)區(qū)分。這種方式的優(yōu)勢(shì)是可以通過(guò)增添容量來(lái)運(yùn)行服務(wù)或?qū)崿F(xiàn)數(shù)據(jù)存儲(chǔ)。

以我們的圖像服務(wù)器為例,將曾經(jīng)儲(chǔ)存在單一的文件服務(wù)器的圖片重新保存到多個(gè)文件服務(wù)器中是可以實(shí)現(xiàn)的,每個(gè)文件服務(wù)器都有自己惟一的圖片集。(見(jiàn)圖表1.4。)這種構(gòu)架允許系統(tǒng)將圖片保存到某個(gè)文件服務(wù)器中,在服務(wù)器都即將存滿(mǎn)時(shí),像增加硬盤(pán)一樣增加額外的服務(wù)器。這種設(shè)計(jì)需要一種能夠?qū)⑽募痛娣欧?wù)器綁定的命名規(guī)則。一個(gè)圖像的名稱(chēng)可能是映射全部服務(wù)器的完整散列方案的形式。或者可選的,每個(gè)圖像都被分配給一個(gè)遞增的 ID,當(dāng)用戶(hù)請(qǐng)求圖像時(shí),圖像檢索服務(wù)只需要保存映射到每個(gè)服務(wù)器的 ID 范圍(類(lèi)似索引)就可以了。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

圖 1.4: 使用冗余和分區(qū)實(shí)現(xiàn)的圖片存儲(chǔ)服務(wù)

當(dāng)然,為多個(gè)服務(wù)器分配數(shù)據(jù)或功能是充滿(mǎn)挑戰(zhàn)的。一個(gè)關(guān)鍵的問(wèn)題就是數(shù)據(jù)局部性;對(duì)于分布式系統(tǒng),計(jì)算或操作的數(shù)據(jù)越相近,系統(tǒng)的性能越佳。因此,一個(gè)潛在的問(wèn)題就是數(shù)據(jù)的存放遍布多個(gè)服務(wù)器,當(dāng)需要一個(gè)數(shù)據(jù)時(shí),它們并不在一起,迫使服務(wù)器不得不為從網(wǎng)絡(luò)中獲取數(shù)據(jù)而付出昂貴的性能代價(jià)。

另一個(gè)潛在的問(wèn)題是不一致性。當(dāng)多個(gè)不同的服務(wù)讀取和寫(xiě)入同一共享資源時(shí),有可能會(huì)遭遇競(jìng)爭(zhēng)狀態(tài)——某些數(shù)據(jù)應(yīng)當(dāng)被更新,但讀取操作恰好發(fā)生在更新之前——這種情形下,數(shù)據(jù)就是不一致的。例如圖像托管方案中可能出現(xiàn)的競(jìng)爭(zhēng)狀態(tài),一個(gè)客戶(hù)端發(fā)送請(qǐng)求,將其某標(biāo)題為“狗”的圖像改名為”小家伙“。而同時(shí)另一個(gè)客戶(hù)端發(fā)送讀取此圖像的請(qǐng)求。第二個(gè)客戶(hù)端中顯示的標(biāo)題是“狗”還是“小家伙”是不能明確的。

當(dāng)然,對(duì)于分區(qū)還有一些障礙存在,但分區(qū)允許將問(wèn)題——數(shù)據(jù)、負(fù)載、使用模式等——切割成可以管理的數(shù)據(jù)塊。這將極大的提高可擴(kuò)展性和可管理性,但并非沒(méi)有風(fēng)險(xiǎn)。有很多可以降低風(fēng)險(xiǎn),處理故障的方法;不過(guò)篇幅有限,不再贅述。若有興趣,可見(jiàn)于此文,獲取更多容錯(cuò)和檢測(cè)的信息。

1.3. 構(gòu)建高效和可伸縮的數(shù)據(jù)訪問(wèn)模塊

在設(shè)計(jì)分布式系統(tǒng)時(shí)一些核心問(wèn)題已經(jīng)考慮到,現(xiàn)在讓我們來(lái)討論下比較困難的一部分:可伸縮的數(shù)據(jù)訪問(wèn)。

對(duì)于大多數(shù)簡(jiǎn)單的web應(yīng)用程序,比如LAMP系統(tǒng),類(lèi)似于圖 Figure 1.5.

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.5: 簡(jiǎn)單web應(yīng)用程序

隨著它們的成長(zhǎng),主要發(fā)生了兩方面的變化:應(yīng)用服務(wù)器和數(shù)據(jù)庫(kù)的擴(kuò)展。在一個(gè)高度可伸縮的應(yīng)用程序中,應(yīng)用服務(wù)器通常最小化并且一般是 shared-nothing架構(gòu)(譯注:shared nothing architecture是一 種分布式計(jì)算架構(gòu),這種架構(gòu)中不存在集中存儲(chǔ)的狀態(tài),整個(gè)系統(tǒng)中沒(méi)有資源競(jìng)爭(zhēng),這種架構(gòu)具有非常強(qiáng)的擴(kuò)張性,在web應(yīng)用中廣泛使用)方式的體現(xiàn),這使得系統(tǒng)的應(yīng)用服務(wù)器層水平可伸縮。由于這種設(shè)計(jì),數(shù)據(jù)庫(kù)服務(wù)器可以支持更多的負(fù)載和服務(wù);在這一層真正的擴(kuò)展和性能改變開(kāi)始發(fā)揮作用了。

剩下的章節(jié)主要集中于通過(guò)一些更常用的策略和方法提供快速的數(shù)據(jù)訪問(wèn)來(lái)使這些類(lèi)型服務(wù)變得更加迅捷。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.6: Oversimplified web application

大多數(shù)系統(tǒng)簡(jiǎn)化為如圖 Figure 1.6所示,這是一個(gè)良好的開(kāi)始。如果你有大量的數(shù)據(jù),你想快捷的訪問(wèn),就像一堆糖果擺放在你辦公室抽屜的最上方。雖然過(guò)于簡(jiǎn)化,前面的聲明暗示了兩個(gè)困難的問(wèn)題:存儲(chǔ)的可伸縮性和數(shù)據(jù)的快速訪問(wèn)。

為了這一節(jié)內(nèi)容,我們假設(shè)你有很大的數(shù)據(jù)存儲(chǔ)空間(TB),并且你想讓用戶(hù)隨機(jī)訪問(wèn)一小部分?jǐn)?shù)據(jù)(查看Figure 1.7)。這類(lèi)似于在圖像應(yīng)用的例子里在文件服務(wù)器定位一個(gè)圖片文件。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.7: Accessing specific data

這非常具有挑戰(zhàn)性,因?yàn)樗枰褦?shù)TB的數(shù)據(jù)加載到內(nèi)存中;并且直接轉(zhuǎn)化為磁盤(pán)的IO。要知道從磁盤(pán)讀取比從內(nèi)存讀取慢很多倍-內(nèi)存的訪問(wèn)速度如同敏捷的查克·諾里斯(譯注:空手道冠軍),而磁盤(pán)的訪問(wèn)速度就像笨重的卡車(chē)一樣。這個(gè)速度差異在大數(shù)據(jù)集上會(huì)增加更多;在實(shí)數(shù)順序讀取上內(nèi)存訪問(wèn)速度至少是磁盤(pán)的6倍,隨機(jī)讀取速度比磁盤(pán)快100,000倍(參考“大數(shù)據(jù)之殤”http://queue.acm.org/detail.cfm?id=1563874)。另外,即使使用唯一的ID,解決獲取少量數(shù)據(jù)存放位置的問(wèn)題也是個(gè)艱巨的任務(wù)。這就如同不用眼睛看在你的糖果存放點(diǎn)取出最后一塊Jolly Rancher口味的糖果一樣。

謝天謝地,有很多方式你可以讓這樣的操作更簡(jiǎn)單些;其中四個(gè)比較重要的是緩存,代理,索引和負(fù)載均衡。本章的剩余部分將討論下如何使用每一個(gè)概念來(lái)使數(shù)據(jù)訪問(wèn)加快。

緩存

緩存利用局部訪問(wèn)原則:最近請(qǐng)求的數(shù)據(jù)可能會(huì)再次被請(qǐng)求。它們幾乎被用于計(jì)算機(jī)的每一層:硬件,操作系統(tǒng),web瀏覽器,web應(yīng)用程序等等。緩存就像短期存儲(chǔ)的內(nèi)存:它有空間的限制,但是通常訪問(wèn)速度比源數(shù)據(jù)源快并且包含了大多數(shù)最近訪問(wèn)的條目。緩存可以在架構(gòu)的各個(gè)層級(jí)存在,但是常常在前端比較常見(jiàn),在這里通常需要在沒(méi)有下游層級(jí)的負(fù)擔(dān)下快速返回?cái)?shù)據(jù)。

在我們的API例子中如何使用緩存來(lái)快速訪問(wèn)數(shù)據(jù)?在這種情況下,有兩個(gè)地方你可以插入緩存。一個(gè)操作是在你的請(qǐng)求層節(jié)點(diǎn)添加一個(gè)緩存,如圖 Figure 1.8.

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.8: Inserting a cache on your request layer node

直接在一個(gè)請(qǐng)求層節(jié)點(diǎn)配置一個(gè)緩存可以在本地存儲(chǔ)相應(yīng)數(shù)據(jù)。每次發(fā)送一個(gè)請(qǐng)求到服務(wù),如果數(shù)據(jù)存在節(jié)點(diǎn)會(huì)快速的返回本地緩存的數(shù)據(jù)。如果數(shù)據(jù)不在緩存中,請(qǐng)求節(jié)點(diǎn)將在磁盤(pán)查找數(shù)據(jù)。請(qǐng)求層節(jié)點(diǎn)緩存可以存放在內(nèi)存和節(jié)點(diǎn)本地磁盤(pán)中(比網(wǎng)絡(luò)存儲(chǔ)快些)。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.9: Multiple caches

當(dāng)你擴(kuò)展這些節(jié)點(diǎn)后會(huì)發(fā)生什么呢?如圖Figure 1.9所示,如果請(qǐng)求層擴(kuò)展為多個(gè)節(jié)點(diǎn),每個(gè)主機(jī)仍然可能有自己的緩存。然而,如果你的負(fù)載均衡器隨機(jī)分配請(qǐng)求到節(jié)點(diǎn),同樣的請(qǐng)求將指向不同的節(jié)點(diǎn),從而增加了緩存的命中缺失率。有兩種選擇可以解決這個(gè)問(wèn)題:全局緩存和分布式緩存。

#p#

全局緩存

全局緩存顧名思義:所有的節(jié)點(diǎn)使用同一個(gè)緩存空間,這涉及到添加一個(gè)服務(wù)器,或者某種文件存儲(chǔ)系統(tǒng),速度比訪問(wèn)源存儲(chǔ)和通過(guò)所有節(jié)點(diǎn)訪問(wèn)要快些。每個(gè)請(qǐng)求節(jié)點(diǎn)以同樣的方式查詢(xún)本地的一個(gè)緩存,這種緩存方案可能有點(diǎn)復(fù)雜,因?yàn)樵诳蛻?hù)端和請(qǐng)求數(shù)量增加時(shí)它很容易被壓倒,但是在有些架構(gòu)里它還是很有用的(尤其是那些專(zhuān)門(mén)的硬件來(lái)使全局緩存變得非常快,或者是固定數(shù)據(jù)集需要被緩存的)。

在描述圖中有兩種常見(jiàn)形式的緩存。在圖Figure 1.10中,當(dāng)一個(gè)緩存響應(yīng)沒(méi)有在緩存中找到時(shí),緩存自身從底層存儲(chǔ)中查找出數(shù)據(jù)。在 Figure 1.11中,當(dāng)在緩存中招不到數(shù)據(jù)時(shí),請(qǐng)求節(jié)點(diǎn)會(huì)向底層去檢索數(shù)據(jù)。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.10: Global cache where cache is responsible for retrieval

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.11: Global cache where request nodes are responsible for retrieval

大多數(shù)使用全局緩存的應(yīng)用程序趨向于第一類(lèi),這類(lèi)緩存可以管理數(shù)據(jù)的讀取,防止客戶(hù)端大量的請(qǐng)求同樣的數(shù)據(jù)。然而,一些情況下,第二類(lèi)實(shí)現(xiàn)方式似乎更有意義。比如,如果一個(gè)緩存被用于非常大的文件,一個(gè)低命中比的緩存將會(huì)導(dǎo)致緩沖區(qū)來(lái)填滿(mǎn)未命中的緩存;在這種情況下,將使緩存中有一個(gè)大比例的總數(shù)據(jù)集。另一個(gè)例子是架構(gòu)設(shè)計(jì)中文件在緩存中存儲(chǔ)是靜態(tài)的并且不會(huì)被排除。(這可能是因?yàn)閼?yīng)用程序要求周?chē)鷶?shù)據(jù)的延遲-某些片段的數(shù)據(jù)可能需要在大數(shù)據(jù)集中非???在有些地方應(yīng)用程序邏輯理清排除策略或者熱點(diǎn) 比緩存方案好使些)

分布式緩存

在分布式緩存(圖1.12)中,每個(gè)節(jié)點(diǎn)都會(huì)緩存一部分?jǐn)?shù)據(jù)。如果把冰箱看作食雜店的緩存的話,那么分布式緩存就象是把你的食物分別放到多個(gè)地方 —— 你的冰箱、柜櫥以及便當(dāng)盒 ——放到這些便于隨時(shí)取用的地方就無(wú)需一趟趟跑去食雜店了。緩存一般使用一個(gè)具有一致性的哈希函數(shù)進(jìn)行分割,如此便可在某請(qǐng)求節(jié)點(diǎn)尋找某數(shù)據(jù)時(shí),能夠迅速知道要到分布式緩存中的哪個(gè)地方去找它,以確定改數(shù)據(jù)是否從緩存中可得。在這種情況下,每個(gè)節(jié)點(diǎn)都有一個(gè)小型緩存,在直接到原數(shù)據(jù)所作處找數(shù)據(jù)之前就可以向別的節(jié)點(diǎn)發(fā)出尋找數(shù)據(jù)的請(qǐng)求。由此可得,分布式緩存的一個(gè)優(yōu)勢(shì)就是,僅僅通過(guò)向請(qǐng)求池中添加新的節(jié)點(diǎn)便可以擁有更多的緩存空間。

分布式緩存的一個(gè)缺點(diǎn)是修復(fù)缺失的節(jié)點(diǎn)。一些分布式緩存系統(tǒng)通過(guò)在不同節(jié)點(diǎn)做多個(gè)備份繞過(guò)了這個(gè)問(wèn)題;然而,你可以想象這個(gè)邏輯迅速變復(fù)雜了,尤其是當(dāng)你在請(qǐng)求層添加或者刪除節(jié)點(diǎn)時(shí)。即便是一個(gè)節(jié)點(diǎn)消失和部分緩存數(shù)據(jù)丟失了,我們還可以在源數(shù)據(jù)存儲(chǔ)地址獲取-因此這不一定是災(zāi)難性的!

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.12: Distributed cache

緩存的偉大之處在于它們使我們的訪問(wèn)速度更快了(當(dāng)然前提是正確使用),你選擇的方法要在更多請(qǐng)求下更快才行。然而,所有這些緩存的代價(jià)是必須有額外的存儲(chǔ)空間,通常在放在昂貴的內(nèi)存中;從來(lái)沒(méi)有嗟來(lái)之食。緩存讓事情處理起來(lái)更快,而且在高負(fù)載情況下提供系統(tǒng)功能,否則將會(huì)使服務(wù)器出現(xiàn)降級(jí)。

有一個(gè)很流行的開(kāi)源緩存項(xiàng)目Memcached (http://memcached.org/)(它可以當(dāng)做一個(gè)本地緩存,也可以用作分布式緩存);當(dāng)然,還有一些其他操作的支持(包括語(yǔ)言包和框架的一些特有設(shè)置)。

Memcached 被用作很多大型的web站點(diǎn),盡管他很強(qiáng)大,但也只是簡(jiǎn)單的內(nèi)存key-value存儲(chǔ)方式,它優(yōu)化了任意數(shù)據(jù)存儲(chǔ)和快速檢索(o(1))。

Facebook使用了多種不同的緩存來(lái)提高他們站點(diǎn)的性能(查看”Facebook caching and performance”)。在語(yǔ)言層面上(使用PHP內(nèi)置函數(shù)調(diào)用)他們使用$GLOBALSand APC緩存,這有助于使中間函數(shù)調(diào)用和結(jié)果返回更快(大多數(shù)語(yǔ)言都有這樣的類(lèi)庫(kù)用來(lái)提高web頁(yè)面的性能)。Facebook使用的全局緩存分布在多個(gè)服務(wù)器上(查看 ”Scaling memcached at Facebook”),這樣一個(gè)訪問(wèn)緩存的函數(shù)調(diào)用可以使用很多并行的請(qǐng)求在不同的Memcached 服務(wù)器上獲取存儲(chǔ)的數(shù)據(jù)。這使得他們?cè)跒橛脩?hù)分配數(shù)據(jù)空間時(shí)有了更高的性能和吞吐量,同時(shí)有一個(gè)中央服務(wù)器做更新(這非常重要,因?yàn)楫?dāng)你運(yùn)行上千服務(wù)器時(shí),緩存失效和一致性將是一個(gè)大挑戰(zhàn))。

現(xiàn)在讓我們討論下當(dāng)數(shù)據(jù)不在緩存中時(shí)該如何處理···

代理

簡(jiǎn)單來(lái)說(shuō),代理服務(wù)器是一種處于客戶(hù)端和服務(wù)器中間的硬件或軟件,它從客戶(hù)端接收請(qǐng)求,并將它們轉(zhuǎn)交給服務(wù)器。代理一般用于過(guò)濾請(qǐng)求、記錄日志或?qū)φ?qǐng)求進(jìn)行轉(zhuǎn)換(增加/刪除頭部、加密/解密、壓縮,等等)。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

圖1.13: 代理服務(wù)器

當(dāng)需要協(xié)調(diào)來(lái)自多個(gè)服務(wù)器的請(qǐng)求時(shí),代理服務(wù)器也十分有用,它允許我們從整個(gè)系統(tǒng)的角度出發(fā)、對(duì)請(qǐng)求流量執(zhí)行優(yōu)化。壓縮轉(zhuǎn)發(fā)(collapsed forwarding)是利用代理加快訪問(wèn)的其中一種方法,將多個(gè)相同或相似的請(qǐng)求壓縮在同一個(gè)請(qǐng)求中,然后將單個(gè)結(jié)果發(fā)送給各個(gè)客戶(hù)端。

假設(shè),有幾個(gè)節(jié)點(diǎn)都希望請(qǐng)求同一份數(shù)據(jù),而且它并不在緩存中。在這些請(qǐng)求經(jīng)過(guò)代理時(shí),代理可以通過(guò)壓縮轉(zhuǎn)發(fā)技術(shù)將它們合并成為一個(gè)請(qǐng)求,這樣一來(lái),數(shù)據(jù)只需要從磁盤(pán)上讀取一次即可(見(jiàn)圖1.14)。這種技術(shù)也有一些缺點(diǎn),由于每個(gè)請(qǐng)求都會(huì)有一些時(shí)延,有些請(qǐng)求會(huì)由于等待與其它請(qǐng)求合并而有所延遲。不管怎么樣,這種技術(shù)在高負(fù)載環(huán)境中是可以幫助提升性能的,特別是在同一份數(shù)據(jù)被反復(fù)訪問(wèn)的情況下。壓縮轉(zhuǎn)發(fā)有點(diǎn)類(lèi)似緩存技術(shù),只不過(guò)它并不對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ),而是充當(dāng)客戶(hù)端的代理人,對(duì)它們的請(qǐng)求進(jìn)行某種程度的優(yōu)化。

在一個(gè)LAN代理服務(wù)器中,客戶(hù)端不需要通過(guò)自己的IP連接到Internet,而代理會(huì)將請(qǐng)求相同內(nèi)容的請(qǐng)求合并起來(lái)。這里比較容易搞混,因?yàn)樵S多代理同時(shí)也充當(dāng)緩存(這里也確實(shí)是一個(gè)很適合放緩存的地方),但緩存卻不一定能當(dāng)代理。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

圖1.14: 通過(guò)代理來(lái)合并請(qǐng)求

另一個(gè)使用代理的方式不只是合并相同數(shù)據(jù)的請(qǐng)求,同時(shí)也可以用來(lái)合并靠近存儲(chǔ)源(一般是磁盤(pán))的數(shù)據(jù)請(qǐng)求。采用這種策略可以讓請(qǐng)求最大化使用本地?cái)?shù)據(jù),這樣可以減少請(qǐng)求的數(shù)據(jù)延遲。比如,一群節(jié)點(diǎn)請(qǐng)求B部分信息:partB1,partB2等,我們可以設(shè)置代理來(lái)識(shí)別各個(gè)請(qǐng)求的空間區(qū)域,然后把它們合并為一個(gè)請(qǐng)求并返回一個(gè)bigB,大大減少了讀取的數(shù)據(jù)來(lái)源(查看圖Figure 1.15)。當(dāng)你隨機(jī)訪問(wèn)上TB數(shù)據(jù)時(shí)這個(gè)請(qǐng)求時(shí)間上的差異就非常明顯了!代理在高負(fù)載情況下,或者限制使用緩存時(shí)特別有用,因?yàn)樗旧峡梢耘康陌讯鄠€(gè)請(qǐng)求合并為一個(gè)。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.15: Using a proxy to collapse requests for data that is spatially close together

值得注意的是,代理和緩存可以放到一起使用,但通常最好把緩存放到代理的前面,放到前面的原因和在參加者眾多的馬拉松比賽中最好讓跑得較快的選手在隊(duì)首起跑一樣。因?yàn)榫彺鎻膬?nèi)存中提取數(shù)據(jù),速度飛快,它并不介意存在對(duì)同一結(jié)果的多個(gè)請(qǐng)求。但是如果緩存位于代理服務(wù)器的另一邊,那么在每個(gè)請(qǐng)求到達(dá) cache之前都會(huì)增加一段額外的時(shí)延,這就會(huì)影響性能。

如果你正想在系統(tǒng)中添加代理,那你可以考慮的選項(xiàng)有很多;SquidVarnish都經(jīng)過(guò)了實(shí)踐檢驗(yàn),廣泛用于很多實(shí)際的web站點(diǎn)中。這些代理解決方案針對(duì)大部分client-server通信提供了大量的優(yōu)化措施。將二者之中的某一個(gè)安裝為web服務(wù)器層的反向代理(reverse proxy,下面負(fù)載均衡器一節(jié)中解釋?zhuān)┛梢源蟠筇岣遷eb服務(wù)器的性能,減少處理來(lái)自客戶(hù)端的請(qǐng)求所需的工作量。

索引

使用索引快速訪問(wèn)數(shù)據(jù)是個(gè)優(yōu)化數(shù)據(jù)訪問(wèn)性能公認(rèn)的策略;可能我們大多數(shù)人都是從數(shù)據(jù)庫(kù)了解到的索引。索引用增長(zhǎng)的存儲(chǔ)空間占用和更慢的寫(xiě)(因?yàn)槟惚仨殞?xiě)和更新索引)來(lái)?yè)Q取更快的讀取。

你可以把這個(gè)概念應(yīng)用到大數(shù)據(jù)集中就像應(yīng)用在傳統(tǒng)的關(guān)系數(shù)據(jù)存儲(chǔ)。索引要關(guān)注的技巧是你必須仔細(xì)考慮用戶(hù)會(huì)怎樣訪問(wèn)你的數(shù)據(jù)。如果數(shù)據(jù)集有很多 TBs,但是每個(gè)數(shù)據(jù)包(payload)很小(可能只有1KB),這時(shí)就必須用索引來(lái)優(yōu)化數(shù)據(jù)訪問(wèn)。在這么大的數(shù)據(jù)集找到小的數(shù)據(jù)包是個(gè)很有挑戰(zhàn)性的工作因?yàn)槟悴豢赡茉诤侠淼臅r(shí)間內(nèi)遍歷所有數(shù)據(jù)。甚至,更有可能的是這么大的數(shù)據(jù)集分布在幾個(gè)(甚至很多個(gè))物理設(shè)備上-這意味著你要用些方法找到期望數(shù)據(jù)的正確物理位置。索引是最適合的方法做這種事情。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.16: Indexes

索引可以作為內(nèi)容的一個(gè)表格-表格的每一項(xiàng)指明你的數(shù)據(jù)存儲(chǔ)的位置。例如,如果你正在查找B的第二部分?jǐn)?shù)據(jù)-你如何知道去哪里找?如果你有個(gè)根據(jù)數(shù)據(jù)類(lèi)型(數(shù)據(jù)A,B,C)排序的索引,索引會(huì)告訴你數(shù)據(jù)B的起點(diǎn)位置。然后你就可以跳轉(zhuǎn)(seek)到那個(gè)位置,讀取你想要的數(shù)據(jù)B的第二部分。 (See Figure 1.16.)

這些索引常常存儲(chǔ)在內(nèi)存中,或者存儲(chǔ)在對(duì)于客戶(hù)端請(qǐng)求來(lái)說(shuō)非??焖俚谋镜匚恢?somewhere very local)。Berkeley DBs (BDBs)和樹(shù)狀數(shù)據(jù)結(jié)構(gòu)常常按順序存儲(chǔ)數(shù)據(jù),非常理想用來(lái)存儲(chǔ)索引。

常常索引有很多層,當(dāng)作數(shù)據(jù)地圖,把你從一個(gè)地方指向另外一個(gè)地方,一直到你的得到你想要的那塊數(shù)據(jù)。(See Figure 1.17.)

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.17: Many layers of indexes

索引也可以用來(lái)創(chuàng)建同樣數(shù)據(jù)的多個(gè)不同視圖(views)。對(duì)于大數(shù)據(jù)集來(lái)說(shuō),這是個(gè)很棒的方法來(lái)定義不同的過(guò)濾器(filter)和類(lèi)別(sort),而不用創(chuàng)建多個(gè)額外的數(shù)據(jù)拷貝。

例如,想象一下,圖片存儲(chǔ)系統(tǒng)開(kāi)始實(shí)際上存儲(chǔ)的是書(shū)的每一頁(yè)的圖像,而且服務(wù)允許客戶(hù)查詢(xún)這些圖片中的文字,搜索每個(gè)主題的所有書(shū)的內(nèi)容,就像搜索引擎允許你搜索HTML內(nèi)容一樣。在這種情況下,所有的書(shū)的圖片占用了很多很多服務(wù)器存儲(chǔ),查找其中的一頁(yè)給用戶(hù)顯示有點(diǎn)難度。首先,用來(lái)查詢(xún)?nèi)我庠~或者詞數(shù)組(tuples)的倒排索引(inverse indexes)需要很容易的訪問(wèn)到;然后,導(dǎo)航到那本書(shū)的確切頁(yè)面和位置并獲取準(zhǔn)確的圖片作為返回結(jié)果,也有點(diǎn)挑戰(zhàn)性。所以,這種境況下,倒排索引應(yīng)該映射到每個(gè)位置(例如書(shū)B(niǎo)),然后B要包含一個(gè)索引每個(gè)部分所有單詞,位置和出現(xiàn)次數(shù)的索引。

可以表示上圖Index1的一個(gè)倒排索引,可能看起來(lái)像下面的樣子-每個(gè)詞或者詞數(shù)組對(duì)應(yīng)一個(gè)包含他們的書(shū)。

Word(s) Book(s)
being awesome Book B, Book C, Book D
always Book C, Book F
believe Book B

這個(gè)中間索引可能看起來(lái)像上面的樣子,但是可能只包含詞,位置和書(shū)B(niǎo)的信息。這種嵌套的索引架構(gòu)要使每個(gè)子索引占用足夠小的空間,以防所有的這些信息必須保存在一個(gè)大的倒排索引中。

這是大型系統(tǒng)的關(guān)鍵點(diǎn),因?yàn)榧词箟嚎s,這些索引也太大,太昂貴(expensive)而難以存儲(chǔ)。在這個(gè)系統(tǒng),如果我們假設(shè)我們世界上的很多書(shū)-100,000,000 (see Inside Google Books blog post)-每個(gè)書(shū)只有10頁(yè)(只是為了下面好計(jì)算),每頁(yè)有250個(gè)詞,那就是2500億(250 billion)個(gè)詞。如果我們假設(shè)每個(gè)詞有5個(gè)字符,每個(gè)字符占用8位(或者1個(gè)字節(jié),即使某些字符要用2個(gè)字節(jié)),所以每個(gè)詞占用5個(gè)字節(jié),那么每個(gè)詞即使只包含一次,這個(gè)索引也要占用超過(guò)1000GB存儲(chǔ)空間。那么,你可以明白創(chuàng)建包含很多其他信息-詞組,數(shù)據(jù)位置和出現(xiàn)次數(shù)-的索引,存儲(chǔ)空間增長(zhǎng)多快了吧。

創(chuàng)建這些中間索引和用更小分段表示數(shù)據(jù),使的大數(shù)據(jù)問(wèn)題可以得到解決。數(shù)據(jù)可以分散到多個(gè)服務(wù)器,訪問(wèn)仍然很快。索引是信息檢索 (information retrieval)的奠基石,是現(xiàn)代搜索引擎的基礎(chǔ)。當(dāng)然,我們這段只是淺顯的介紹,還有其他很多深入研究沒(méi)有涉及-例如如何使索引更快,更小,包含更多信息(例如關(guān)聯(lián)(relevancy)),和無(wú)縫的更新(在競(jìng)爭(zhēng)條件下(race conditions),有一些管理性難題;在海量添加或者修改數(shù)據(jù)的更新中,尤其還涉及到關(guān)聯(lián)(relevancy)和得分(scoring),也有一些難題)。

快速簡(jiǎn)便的查找到數(shù)據(jù)是很重要的;索引是可以達(dá)到這個(gè)目的有效簡(jiǎn)單工具。

負(fù)載均衡器

最后還要講講所有分布式系統(tǒng)中另一個(gè)比較關(guān)鍵的部分,負(fù)載均衡器。負(fù)載均衡器是各種體系結(jié)構(gòu)中一個(gè)不可或缺的部分,因?yàn)樗鼈儞?dān)負(fù)著將負(fù)載在處理服務(wù)請(qǐng)求的一組節(jié)點(diǎn)中進(jìn)行分配的任務(wù)。這樣就可以讓系統(tǒng)中的多個(gè)節(jié)點(diǎn)透明地服務(wù)于同一個(gè)功能(參見(jiàn)圖1.18)。它的主要目的就是要處理大量并發(fā)的連接并將這些連接分配給某個(gè)請(qǐng)求處理節(jié)點(diǎn),從而可使系統(tǒng)具有伸縮性,僅僅通過(guò)添加新節(jié)點(diǎn)便能處理更多的請(qǐng)求。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

圖1.18: 負(fù)載均衡器

用于處理這些請(qǐng)求的算法有很多種,包括隨機(jī)選取節(jié)點(diǎn)、循環(huán)式選取,甚至可以按照內(nèi)存或CPU的利用率等等這樣特定的條件進(jìn)行節(jié)點(diǎn)選取。負(fù)載均衡器可以用軟件或硬件設(shè)備來(lái)實(shí)現(xiàn)。近來(lái)得到廣泛應(yīng)用的一個(gè)開(kāi)源的軟件負(fù)載均衡器叫做 HAProxy)。

在分布式系統(tǒng)中,負(fù)載均衡器往往處于系統(tǒng)的最前端,這樣所有發(fā)來(lái)的請(qǐng)求才能進(jìn)行相應(yīng)的分發(fā)。在一些比較復(fù)雜的分布式系統(tǒng)中,將一個(gè)請(qǐng)求分發(fā)給多個(gè)負(fù)載均衡器也是常事,如圖1.19所示。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

圖1.19: 多重負(fù)載均衡器

和代理類(lèi)似,有些負(fù)載均衡器還可以基于請(qǐng)求的類(lèi)型對(duì)不同的請(qǐng)求進(jìn)行不同的處理(技術(shù)上講,這樣的叫做反向代理)。

負(fù)載均衡器面臨的一個(gè)難題是怎么管理同用戶(hù)的session相關(guān)的數(shù)據(jù)。在電子商務(wù)網(wǎng)站中,如果你只有一個(gè)客戶(hù)端,那么很容易就可以把用戶(hù)放入購(gòu)物車(chē)?yán)锏臇|西保存起來(lái),等他下次訪問(wèn)訪問(wèn)時(shí)購(gòu)物車(chē)?yán)锶阅芸吹侥切〇|西(這很重要,因?yàn)楫?dāng)用戶(hù)回來(lái)發(fā)現(xiàn)仍然呆在購(gòu)物車(chē)?yán)锏漠a(chǎn)品時(shí)很有可能就會(huì)買(mǎi)它)。然而,如果在一個(gè)session中將用戶(hù)分發(fā)到了某個(gè)節(jié)點(diǎn),但該用戶(hù)下次訪問(wèn)時(shí)卻分發(fā)到了另外一個(gè)節(jié)點(diǎn),這里就有可能產(chǎn)生不一致性,因?yàn)樾碌墓?jié)點(diǎn)可能就沒(méi)有保留下用戶(hù)購(gòu)物車(chē)?yán)锏臇|西。(要是你把6盒子子農(nóng)夫山泉放到購(gòu)物車(chē)?yán)锪?,可下次回?lái)一看購(gòu)物車(chē)空了,難道你不會(huì)發(fā)火嗎?) 解決該問(wèn)題的一個(gè)方法是可以使session具有保持性,讓同一用戶(hù)總是分發(fā)到同一個(gè)節(jié)點(diǎn)之上,但這樣一來(lái)就很難利用類(lèi)似failover這樣的可靠性措施了。如果這樣的話,用戶(hù)的購(gòu)物車(chē)?yán)锏臇|西不會(huì)丟,但如果用戶(hù)保持的那個(gè)節(jié)點(diǎn)失效,就會(huì)出現(xiàn)一種特殊的情況,購(gòu)物車(chē)?yán)锏臇|西不會(huì)丟這個(gè)假設(shè)再也不成立了(雖然但愿不要把這個(gè)假設(shè)寫(xiě)到程序里)。當(dāng)然,這個(gè)問(wèn)題還可以用本章中講到的其它策略和工具來(lái)解決,比如服務(wù)以及許多并沒(méi)有講到的方法(象服務(wù)器緩存、 cookie以及URL重寫(xiě))。

如果系統(tǒng)中只有不太多的節(jié)點(diǎn),循環(huán)式(round robin)DNS系統(tǒng)這樣的方案也許更有意義,因?yàn)樨?fù)載均衡器可能比較貴,而且還額外增加了一層沒(méi)必要的復(fù)雜性。當(dāng)然,在比較大的系統(tǒng)中會(huì)有各種各樣的調(diào)度以及負(fù)載均衡算法,簡(jiǎn)單點(diǎn)的有隨機(jī)選取或循環(huán)式選取,復(fù)雜點(diǎn)的可以考慮上利用率以及處理能力這些因素。所有這些算法都是對(duì)瀏覽和請(qǐng)求進(jìn)行分發(fā),并能提供很有用的可靠性工具,比如自動(dòng)failover或者自動(dòng)提出失效節(jié)點(diǎn)(比如節(jié)點(diǎn)失去響應(yīng))。然而,這些高級(jí)特性會(huì)讓問(wèn)題診斷難以進(jìn)行。例如,當(dāng)系統(tǒng)載荷較大時(shí),負(fù)載均衡器可能會(huì)移除慢速或者超時(shí)的節(jié)點(diǎn)(由于節(jié)點(diǎn)要處理大量請(qǐng)求),但對(duì)其它節(jié)點(diǎn)而言,這么做實(shí)際上是加劇了情況的惡化程度。在這時(shí)進(jìn)行大量的監(jiān)測(cè)非常重要,因?yàn)橄到y(tǒng)總體流量和吞吐率可能看上去是在下降(因?yàn)楣?jié)點(diǎn)處理的請(qǐng)求變少了),但個(gè)別節(jié)點(diǎn)卻越來(lái)越忙得不可開(kāi)交。

負(fù)載均衡器是一種能讓你擴(kuò)展系統(tǒng)能力的簡(jiǎn)單易行的方式,和本文中所講的其它技術(shù)一樣,它在分布式系統(tǒng)架構(gòu)中起著基礎(chǔ)性的作用。負(fù)載均衡器還要提供一個(gè)比較關(guān)鍵的功能,它必需能夠探測(cè)出節(jié)點(diǎn)的運(yùn)行狀況,比如,如果一個(gè)節(jié)點(diǎn)失去響應(yīng)或處于過(guò)載狀態(tài),負(fù)載均衡器可以將其總處理請(qǐng)求的節(jié)點(diǎn)池中移除出去,還接著使用系統(tǒng)中冗余的其它不同節(jié)點(diǎn)。

#p#

隊(duì)列

目前為止我們已經(jīng)介紹了許多更快讀取數(shù)據(jù)的方法,但另一個(gè)使數(shù)據(jù)層具伸縮性的重要部分是對(duì)寫(xiě)的有效管理。當(dāng)系統(tǒng)簡(jiǎn)單的時(shí)候,只有最小的處理負(fù)載和很小的數(shù)據(jù)庫(kù),寫(xiě)的有多快可以預(yù)知;然而,在更復(fù)雜的系統(tǒng),寫(xiě)可能需要幾乎無(wú)法決定的長(zhǎng)久時(shí)間。例如,數(shù)據(jù)可能必須寫(xiě)到不同數(shù)據(jù)庫(kù)或索引中的幾個(gè)地方,或者系統(tǒng)可能正好處于高負(fù)載。這些情況下,寫(xiě)或者任何那一類(lèi)任務(wù),有可能需要很長(zhǎng)的時(shí)間,追求性能和可用性需要在系統(tǒng)中創(chuàng)建異步;一個(gè)通常的做到那一點(diǎn)的辦法是通過(guò)隊(duì)列。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

Figure 1.20: Synchronous request

設(shè)想一個(gè)系統(tǒng),每個(gè)客戶(hù)端都在發(fā)起一個(gè)遠(yuǎn)程服務(wù)的任務(wù)請(qǐng)求。每一個(gè)客戶(hù)端都向服務(wù)器發(fā)送它們的請(qǐng)求,服務(wù)器盡可能快的完成這些任務(wù),并分別返回結(jié)果給各個(gè)客戶(hù)端。在一個(gè)小型系統(tǒng),一個(gè)服務(wù)器(或邏輯服務(wù))可以給傳入的客戶(hù)端請(qǐng)求提供迅速服務(wù),就像它們來(lái)的一樣快,這種情形應(yīng)該工作的很好。然而,當(dāng)服務(wù)器收到了超過(guò)它所能處理數(shù)量的請(qǐng)求時(shí),每個(gè)客戶(hù)端在產(chǎn)生一個(gè)響應(yīng)前,將被迫等待其他客戶(hù)端的請(qǐng)求結(jié)束。這是一個(gè)同步請(qǐng)求的例子,示意在圖1.20。

這種同步的行為會(huì)嚴(yán)重的降低客戶(hù)端性能;客戶(hù)端被迫等待,有效的執(zhí)行零工作,直到它的請(qǐng)求被應(yīng)答。添加額外的服務(wù)器承擔(dān)系統(tǒng)負(fù)載也不會(huì)解決這個(gè)問(wèn)題;即使是有效的負(fù)載均衡,為了最大化客戶(hù)端性能,保證平等的公平的分發(fā)工作也是極其困難的。而且,如果服務(wù)器處理請(qǐng)求不可及,或者失敗了,客戶(hù)端上行也會(huì)失敗。有效解決這個(gè)問(wèn)題在于,需要在客戶(hù)端請(qǐng)求與實(shí)際的提供服務(wù)的被執(zhí)行工作之間建立抽象。

可擴(kuò)展Web架構(gòu)與分布式系統(tǒng)

圖 1.21:用隊(duì)列管理請(qǐng)求

進(jìn)入隊(duì)列。一個(gè)隊(duì)列就像它聽(tīng)起來(lái)那么簡(jiǎn)單:一個(gè)任務(wù)進(jìn)入,被加入隊(duì)列然后工人們只要有能力去處理就會(huì)拿起下一個(gè)任務(wù)。(看圖1.21)這些任務(wù)可能是代表了簡(jiǎn)單的寫(xiě)數(shù)據(jù)庫(kù),或者一些復(fù)雜的事情,像為一個(gè)文檔生成一個(gè)縮略預(yù)覽圖一類(lèi)的。當(dāng)一個(gè)客戶(hù)端提交一個(gè)任務(wù)請(qǐng)求到一個(gè)隊(duì)列,它們?cè)僖膊粫?huì)被迫等待結(jié)果;它們只需要確認(rèn)請(qǐng)求被正確的接收了。這個(gè)確認(rèn)之后可能在客戶(hù)端請(qǐng)求的時(shí)候,作為一個(gè)工作結(jié)果的參考。

隊(duì)列使客戶(hù)端能以異步的方式工作,提供了一個(gè)客戶(hù)端請(qǐng)求與其響應(yīng)的戰(zhàn)略抽象。換句話說(shuō),在一個(gè)同步系統(tǒng),沒(méi)有請(qǐng)求與響應(yīng)的區(qū)別,因此它們不能被單獨(dú)的管理。在一個(gè)異步的系統(tǒng),客戶(hù)端請(qǐng)求一個(gè)任務(wù),服務(wù)端響應(yīng)一個(gè)任務(wù)已收到的確認(rèn),然后客戶(hù)端可以周期性的檢查任務(wù)的狀態(tài),一旦它結(jié)束就請(qǐng)求結(jié)果。當(dāng)客戶(hù)端等待一個(gè)異步的請(qǐng)求完成,它可以自由執(zhí)行其它工作,甚至異步請(qǐng)求其它的服務(wù)。后者是隊(duì)列與消息在分布式系統(tǒng)如何成為杠桿的例子。

隊(duì)列也對(duì)服務(wù)中斷和失敗提供了防護(hù)。例如,創(chuàng)建一個(gè)高度強(qiáng)健的隊(duì)列,這個(gè)隊(duì)列能夠重新嘗試由于瞬間服務(wù)器故障而失敗的服務(wù)請(qǐng)求,是非常容易的事。相比直接暴露客戶(hù)端于間歇性服務(wù)中斷,需要復(fù)雜的而且經(jīng)常矛盾的客戶(hù)端錯(cuò)誤處理程序,用一個(gè)隊(duì)列去加強(qiáng)服務(wù)質(zhì)量的擔(dān)保更為可取。

隊(duì)列對(duì)管理任何大規(guī)模分布式系統(tǒng)不同部分之間的分布式通信,是一個(gè)基礎(chǔ),而且實(shí)現(xiàn)它們有許多的方法。有不少開(kāi)源的隊(duì)列如 RabbitMQActiveMQBeanstalkD,但是有些也用像 Zookeeper的服務(wù),或者甚至像Redis的數(shù)據(jù)存儲(chǔ)。

1.4. 結(jié)論

設(shè)計(jì)有效的系統(tǒng)來(lái)進(jìn)行快速的大數(shù)據(jù)訪問(wèn)是有趣的,同時(shí)有大量的好工具來(lái)幫助各種各樣的應(yīng)用程序進(jìn)行設(shè)計(jì)。 這文章只覆蓋了一些例子,僅僅是一些表面的東西,但將會(huì)越來(lái)越多–同時(shí)在這個(gè)領(lǐng)域里一定會(huì)繼續(xù)有更多創(chuàng)新東西。

英文原文:Scalable Web Architecture and Distributed Systems

譯文鏈接:http://www.oschina.net/translate/scalable-web-architecture-and-distributed-systems

責(zé)任編輯:林師授 來(lái)源: OSChina翻譯
相關(guān)推薦

2024-10-10 14:01:34

2023-05-29 14:07:00

Zuul網(wǎng)關(guān)系統(tǒng)

2025-02-14 08:50:00

架構(gòu)開(kāi)發(fā)軟件

2023-10-09 09:27:33

Docker容器

2022-10-19 08:39:46

?可?分布式集群

2019-10-10 09:16:34

Zookeeper架構(gòu)分布式

2017-09-04 08:49:17

存儲(chǔ)原理架構(gòu)

2017-12-20 16:15:30

分布式系統(tǒng)架構(gòu)

2019-12-26 08:59:20

Redis主從架構(gòu)

2023-05-12 08:23:03

分布式系統(tǒng)網(wǎng)絡(luò)

2018-12-14 10:06:22

緩存分布式系統(tǒng)

2017-10-27 08:40:44

分布式存儲(chǔ)剪枝系統(tǒng)

2023-10-26 18:10:43

分布式并行技術(shù)系統(tǒng)

2023-12-22 14:05:00

MongoDB分布式數(shù)據(jù)庫(kù)

2023-02-11 00:04:17

分布式系統(tǒng)安全

2023-09-14 15:38:55

云原生分布式架構(gòu)

2024-03-25 08:35:07

分布式系統(tǒng)設(shè)計(jì)

2015-08-03 15:48:42

Hadoop大數(shù)據(jù)

2016-08-12 15:17:40

分布式

2017-10-19 08:45:15

存儲(chǔ)系統(tǒng)HBase
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)