可擴(kuò)展的Web體系結(jié)構(gòu)和分布式系統(tǒng)

本篇文章英文版鏈接:Scalable Web Architecture and Distributed Systems Kate Matsudaira募疮。這篇文章簡(jiǎn)略地描述了分布式架構(gòu)是怎么來解決系統(tǒng)擴(kuò)展性問題。

開源軟件已經(jīng)成為一些大型網(wǎng)站的基本構(gòu)件。隨著這些網(wǎng)站的發(fā)展理朋,圍繞其架構(gòu)的最佳實(shí)踐和指導(dǎo)原則也出現(xiàn)了犀变。本章旨在介紹設(shè)計(jì)大型網(wǎng)站時(shí)需要考慮的一些關(guān)鍵問題梯找,以及實(shí)現(xiàn)這些目標(biāo)所需的一些構(gòu)建模塊诊胞。

本篇文章主要關(guān)注web系統(tǒng)沙峻,盡管其中一些內(nèi)容也適用于其他分布式系統(tǒng)睦授。

1. Web分布式系統(tǒng)設(shè)計(jì)原則

構(gòu)建和運(yùn)行一個(gè)可擴(kuò)展的web站點(diǎn)或應(yīng)用程序究竟意味著什么?在最原始級(jí)別上摔寨,它只是通過互聯(lián)網(wǎng)將用戶與遠(yuǎn)程資源連接起來 -- 使其可伸縮的部分是資源去枷,或?qū)@些資源的訪問,分布在多個(gè)服務(wù)器上是复。

就像生活中的大多數(shù)事情一樣沉填,在構(gòu)建web服務(wù)時(shí)提前做計(jì)劃從長(zhǎng)遠(yuǎn)來看是有幫助的;了解大型網(wǎng)站背后的一些考慮因素和權(quán)衡可以在創(chuàng)建小型網(wǎng)站時(shí)做出更明智的決策佑笋。以下是影響大型web系統(tǒng)設(shè)計(jì)的一些關(guān)鍵原則:

  • 可用性:網(wǎng)站的正常運(yùn)行時(shí)間對(duì)許多公司的聲譽(yù)和功能都至關(guān)重要翼闹。對(duì)于一些規(guī)模較大的在線零售網(wǎng)站來說,即使只有幾分鐘時(shí)間不可用蒋纬,也會(huì)導(dǎo)致成千上萬甚至數(shù)百萬美元的收入損失猎荠,因此坚弱,設(shè)計(jì)能夠持續(xù)可用的系統(tǒng),并對(duì)失敗保持彈性关摇,既是一項(xiàng)基本業(yè)務(wù)荒叶,也是一項(xiàng)技術(shù)要求。分布式系統(tǒng)中的高可用性要求仔細(xì)考慮關(guān)鍵組件的冗余输虱、部分系統(tǒng)故障時(shí)的快速恢復(fù)以及出現(xiàn)問題時(shí)的優(yōu)雅降級(jí)些楣。
  • 性能:網(wǎng)站性能已經(jīng)成為大多數(shù)網(wǎng)站的一個(gè)重要考慮因素。網(wǎng)站的速度會(huì)影響用戶的使用和滿意度宪睹,以及搜索引擎的排名愁茁,這是一個(gè)與收入和用戶留存率直接相關(guān)的因素。因此亭病,創(chuàng)建一個(gè)針對(duì)快速響應(yīng)和低延遲進(jìn)行優(yōu)化的系統(tǒng)是關(guān)鍵鹅很。
  • 可靠性:系統(tǒng)需要可靠,這樣對(duì)數(shù)據(jù)的請(qǐng)求將始終返回相同的數(shù)據(jù)罪帖。如果數(shù)據(jù)發(fā)生更改或更新促煮,那么相同的請(qǐng)求應(yīng)該返回新數(shù)據(jù)。用戶需要知道整袁,如果向系統(tǒng)寫入或存儲(chǔ)了某些內(nèi)容菠齿,那么這些內(nèi)容將會(huì)持久存在,并且可以依賴于這些內(nèi)容以備將來檢索坐昙。
  • 可伸縮性:對(duì)于任何大型分布式系統(tǒng)绳匀,規(guī)模只是需要考慮的一個(gè)方面。同樣重要的是增加處理更大負(fù)載的能力所需要的精力民珍,通常稱為系統(tǒng)的可伸縮性〉领可伸縮性可以參考系統(tǒng)的許多不同參數(shù):它可以處理多少額外的流量嚷量、添加更多的存儲(chǔ)容量有多容易,甚至可以處理多少事務(wù)逆趣。
  • 可管理性:設(shè)計(jì)一個(gè)易于操作的系統(tǒng)是另一個(gè)重要的考慮因素蝶溶。系統(tǒng)的可管理性等同于操作的可伸縮性:維護(hù)和更新。要考慮可管理性宣渗,需要考慮的問題包括:當(dāng)問題發(fā)生時(shí)抖所,診斷和理解問題是否容易,更新或修改是否容易痕囱,以及系統(tǒng)操作是否簡(jiǎn)單田轧。(即它是否正常運(yùn)行,沒有故障或異常?)
  • 成本:成本是一個(gè)重要因素鞍恢。這顯然包括硬件和軟件成本傻粘,但是考慮部署和維護(hù)系統(tǒng)所需的其他方面也很重要每窖。應(yīng)該考慮開發(fā)人員構(gòu)建系統(tǒng)所需的時(shí)間、運(yùn)行系統(tǒng)所需的操作工作量弦悉,甚至需要的培訓(xùn)量窒典。

這些原則中的每一個(gè)都為設(shè)計(jì)分布式web體系結(jié)構(gòu)的決策提供了基礎(chǔ)。然而稽莉,它們也可能彼此不一致瀑志,以至于實(shí)現(xiàn)一個(gè)目標(biāo)的代價(jià)是另一個(gè)目標(biāo)。一個(gè)基本示例:選擇通過簡(jiǎn)單地添加更多服務(wù)器(可伸縮性)來解決容量問題污秆,可能要付出可管理性(必須操作額外的服務(wù)器)和成本(服務(wù)器的價(jià)格)的代價(jià)劈猪。

2. 基礎(chǔ)

當(dāng)涉及到系統(tǒng)架構(gòu)時(shí),有一些事情需要考慮:什么是正確的部分混狠,這些部分如何組合在一起岸霹,以及什么是正確的權(quán)衡。在需要之前投資于規(guī)模通常不是明智的商業(yè)主張将饺;但是贡避,對(duì)設(shè)計(jì)進(jìn)行一些前瞻性的考慮可以在未來節(jié)省大量的時(shí)間和資源。

本節(jié)主要討論幾乎所有大型web應(yīng)用程序的核心因素:服務(wù)予弧、冗余刮吧、分區(qū)和故障處理。每一個(gè)因素都涉及選擇和妥協(xié)掖蛤,特別是在上一節(jié)描述的原則的上下文中杀捻。為了詳細(xì)解釋這些,最好從一個(gè)例子開始蚓庭。

2.1 示例:圖像托管應(yīng)用程序

在某些時(shí)候致讥,你可能要在網(wǎng)上發(fā)布一張圖片。對(duì)于承載和傳送大量圖像的大型站點(diǎn)器赞,在構(gòu)建具有成本效益垢袱、高可用性和低延遲(快速檢索)的體系結(jié)構(gòu)方面存在挑戰(zhàn)。

設(shè)想這樣一個(gè)系統(tǒng)港柜,用戶可以將自己的圖像上傳到中央服務(wù)器请契,并且可以通過web鏈接或API請(qǐng)求圖像,就像Flickr或Picasa一樣夏醉。為了簡(jiǎn)單起見爽锥,我們假設(shè)這個(gè)應(yīng)用程序有兩個(gè)關(guān)鍵部分:上傳(寫)圖像到服務(wù)器的能力,以及查詢圖像的能力畔柔。雖然我們當(dāng)然希望上傳是高效的氯夷,但我們最關(guān)心的是當(dāng)有人請(qǐng)求一個(gè)圖像時(shí)(例如,可以為web頁(yè)面或其他應(yīng)用程序請(qǐng)求圖像)能夠非嘲胁粒快速地傳輸肠槽。這與web服務(wù)器或內(nèi)容交付網(wǎng)絡(luò)(CDN)邊緣服務(wù)器(服務(wù)器CDN用于在許多位置存儲(chǔ)內(nèi)容擎淤,因此內(nèi)容在地理上/物理上更接近用戶,從而提高性能)可能提供的功能非常相似秸仙。

該系統(tǒng)的其他重要方面包括:

  • 存儲(chǔ)的圖像的數(shù)量沒有限制嘴拢,因此需要考慮存儲(chǔ)的可擴(kuò)展性(就圖像數(shù)量而言)。
  • 圖像下載/請(qǐng)求需要較低的延遲寂纪。
  • 如果用戶上傳了一個(gè)圖像席吴,那么圖像應(yīng)該始終存在(圖像的數(shù)據(jù)可靠性)。
  • 系統(tǒng)應(yīng)該易于維護(hù)(可管理性)捞蛋。
  • 由于圖像托管沒有很高的利潤(rùn)率孝冒,系統(tǒng)需要具有成本效益

圖1.1是功能的簡(jiǎn)化圖。

圖1.1:圖像托管應(yīng)用程序的簡(jiǎn)化架構(gòu)圖

在這個(gè)圖像托管示例中拟杉,系統(tǒng)必須速度快庄涡,數(shù)據(jù)存儲(chǔ)可靠,并且所有這些屬性都具有很高的可伸縮性搬设。構(gòu)建這個(gè)應(yīng)用程序的小版本非常簡(jiǎn)單穴店,并且很容易托管在一臺(tái)服務(wù)器上;然而拿穴,這對(duì)于本文章來說并不有趣泣洞。假設(shè)我們想建立一個(gè)像Flickr一樣大的東西。

2.2 服務(wù)

在考慮可擴(kuò)展的系統(tǒng)設(shè)計(jì)時(shí)默色,它有助于將功能解耦球凰,并將系統(tǒng)的每個(gè)部分看作具有明確定義的接口的自己的服務(wù)。在實(shí)踐中腿宰,以這種方式設(shè)計(jì)的系統(tǒng)被稱為具有面向服務(wù)的體系結(jié)構(gòu)(SOA)呕诉。對(duì)于這些類型的系統(tǒng),每個(gè)服務(wù)都有自己獨(dú)特的功能上下文吃度,并且通過抽象接口(通常是另一個(gè)服務(wù)的面向公共的API)與上下文之外的任何東西進(jìn)行交互甩挫。

將系統(tǒng)分解為一組互補(bǔ)的服務(wù),可以將這些部分的操作彼此解耦规肴。這種抽象有助于在服務(wù)捶闸、其基礎(chǔ)環(huán)境和服務(wù)的消費(fèi)者之間建立清晰的關(guān)系夜畴。創(chuàng)建這些清晰的描述可以幫助隔離問題拖刃,但也允許每個(gè)部分獨(dú)立地伸縮。這種面向服務(wù)的系統(tǒng)設(shè)計(jì)與面向?qū)ο蟮木幊淘O(shè)計(jì)非常相似贪绘。

在我們的例子中兑牡,所有上傳和檢索圖像的請(qǐng)求都由同一臺(tái)服務(wù)器處理;然而税灌,由于系統(tǒng)需要擴(kuò)展均函,將這兩個(gè)功能分解為各自的服務(wù)是有意義的亿虽。

假設(shè)服務(wù)正在大量使用;這樣的場(chǎng)景很容易看出寫操作的時(shí)間會(huì)影響讀取圖像所需的時(shí)間(因?yàn)檫@兩個(gè)函數(shù)將爭(zhēng)奪共享資源)苞也。根據(jù)架構(gòu)的不同洛勉,這種效果可能非常顯著。即使上傳和下載速度是相同的(這是不正確的IP網(wǎng)絡(luò)如迟,因?yàn)榇蠖鄶?shù)網(wǎng)絡(luò)用于下載速度:上傳速度的比例至少為3:1)收毫,讀取文件通常會(huì)被從緩存中讀取,寫入最終將不得不去磁盤殷勘。即使所有內(nèi)容都在內(nèi)存中或從磁盤讀取(如ssd)此再,數(shù)據(jù)庫(kù)寫操作也幾乎總是比讀取操作慢。

這種設(shè)計(jì)的另一個(gè)潛在問題是玲销,像Apache或lighttpd這樣的web服務(wù)器通常對(duì)它可以維護(hù)的并發(fā)連接的數(shù)量有一個(gè)上限(默認(rèn)值大約是500個(gè)输拇,但是可以更高),并且在高流量中贤斜,寫操作可以快速地消耗所有這些連接策吠。因?yàn)榭梢援惒阶x取,或利用其他性能優(yōu)化,如gzip壓縮或分塊傳輸編碼,web服務(wù)器可以切換為讀取速度更快,迅速切換服務(wù)更多的每秒請(qǐng)求的最大連接數(shù)(與Apache和最大連接設(shè)置為500,它并不少見為每秒幾千讀請(qǐng)求)。另一方面蠢古,寫操作傾向于在上傳期間保持開放連接奴曙,因此上傳1MB的文件在大多數(shù)家庭網(wǎng)絡(luò)上可能需要超過1秒的時(shí)間,因此web服務(wù)器只能同時(shí)處理500個(gè)這樣的寫操作草讶。


圖1.2:劃分讀和寫

如圖1.2所示洽糟,針對(duì)這類瓶頸的規(guī)劃很好地將圖像的讀寫分離到它們自己的服務(wù)中。這使我們能夠獨(dú)立地對(duì)它們進(jìn)行伸縮(因?yàn)槲覀兒芸赡芸偸亲x多于寫)堕战,但也有助于闡明在每個(gè)點(diǎn)上發(fā)生了什么坤溃。最后,這將分離未來的關(guān)注點(diǎn)嘱丢,這將使故障排除和擴(kuò)展慢讀等問題變得更容易薪介。

這種方法的優(yōu)點(diǎn)是我們能夠獨(dú)立于其他方法解決問題 — 我們不必?fù)?dān)心在相同的上下文中寫入和檢索新圖像。這兩種服務(wù)仍然利用全局圖像庫(kù)越驻,但是它們可以自由地使用適合服務(wù)的方法優(yōu)化自己的性能(例如汁政,排隊(duì)請(qǐng)求,或緩存流行的圖像 — 下面將詳細(xì)介紹)缀旁。從維護(hù)和成本的角度來看记劈,每個(gè)服務(wù)都可以根據(jù)需要獨(dú)立伸縮,這很好并巍,因?yàn)槿绻麑⑺鼈兘M合在一起并混合在一起目木,一個(gè)服務(wù)可能會(huì)在不經(jīng)意間影響另一個(gè)服務(wù)的性能,就像上面討論的場(chǎng)景一樣懊渡。

當(dāng)然刽射,當(dāng)你有兩個(gè)不同的端點(diǎn)時(shí)军拟,上面的示例可以很好地工作(事實(shí)上,這與幾個(gè)云存儲(chǔ)提供商的實(shí)現(xiàn)和內(nèi)容交付網(wǎng)絡(luò)非常相似)誓禁。盡管有很多方法可以解決這些類型的瓶頸懈息,但是每種方法都有不同的權(quán)衡。

例如摹恰,F(xiàn)lickr通過分發(fā)用戶在不同的分配上來解決這個(gè)讀/寫問題漓拾,每一個(gè)分片只能處理一定數(shù)量的用戶,當(dāng)用戶增加則更多的分片被添加到集群戒祠。在第一個(gè)例子中骇两,根據(jù)實(shí)際使用情況(整個(gè)系統(tǒng)的讀和寫數(shù)量)對(duì)硬件進(jìn)行伸縮比較容易,而Flickr則根據(jù)用戶基數(shù)進(jìn)行伸縮(但是必須假設(shè)用戶之間的使用情況相同姜盈,這樣才能有額外的容量)低千。在前一種情況下,一個(gè)服務(wù)的宕機(jī)或問題會(huì)導(dǎo)致整個(gè)系統(tǒng)的功能下降(例如馏颂,沒有人可以寫文件)示血,而Flickr的一個(gè)分片宕機(jī)只會(huì)影響這些用戶。在第一個(gè)例子更容易在整個(gè)數(shù)據(jù)集執(zhí)行操作 - 例如救拉,更新寫服務(wù)包括新的元數(shù)據(jù)或搜索在所有圖像元數(shù)據(jù) - 然而Flickr的每個(gè)分片需要更新或搜索(或搜索服務(wù)將需要?jiǎng)?chuàng)建整理元數(shù)據(jù) - 實(shí)際上他們就是這么做的)难审。

這些系統(tǒng)沒有正確答案,但它有助于回到在這一章的開始的原則亿絮,確定系統(tǒng)需要(讀頻繁告喊,寫頻繁,或兩者都比較頻繁派昧,并發(fā)性的級(jí)別黔姜,整個(gè)數(shù)據(jù)集查詢,范圍,排序,等等),選擇不同的備選方案蒂萎,了解系統(tǒng)如何將失敗秆吵,當(dāng)失敗發(fā)生時(shí),有一個(gè)可靠的計(jì)劃五慈。

2.3 冗余

為了優(yōu)雅地處理故障纳寂,web體系結(jié)構(gòu)必須有其服務(wù)和數(shù)據(jù)的冗余。例如泻拦,如果單個(gè)服務(wù)器上只有一個(gè)文件副本毙芜,那么丟失該服務(wù)器就意味著丟失該文件。丟失數(shù)據(jù)很少是件好事聪轿,處理它的一種常見方法是創(chuàng)建多個(gè)或冗余的副本爷肝。

同樣的原則也適用于服務(wù)猾浦。如果應(yīng)用程序有一個(gè)核心功能陆错,那么確保同時(shí)運(yùn)行多個(gè)副本或版本可以防止單個(gè)節(jié)點(diǎn)發(fā)生故障灯抛。

在系統(tǒng)中創(chuàng)建冗余可以消除單點(diǎn)故障,并在危機(jī)中提供備份或備用功能音瓷。例如对嚼,如果在生產(chǎn)環(huán)境中運(yùn)行兩個(gè)相同服務(wù)的實(shí)例,其中一個(gè)出現(xiàn)故障或降級(jí)绳慎,則系統(tǒng)可以故障轉(zhuǎn)移到正常副本纵竖。故障轉(zhuǎn)移可以自動(dòng)發(fā)生,也可以需要手動(dòng)干預(yù)杏愤。

服務(wù)冗余的另一個(gè)關(guān)鍵部分是創(chuàng)建無共享體系結(jié)構(gòu)靡砌。使用這種體系結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都能夠獨(dú)立于其他節(jié)點(diǎn)進(jìn)行操作珊楼,并且沒有中央“大腦”管理其他節(jié)點(diǎn)的狀態(tài)或協(xié)調(diào)活動(dòng)通殃。這對(duì)可伸縮性有很大幫助,因?yàn)榭梢栽跊]有特殊條件或知識(shí)的情況下添加新節(jié)點(diǎn)厕宗。然而画舌,最重要的是,在這些系統(tǒng)中沒有單一的故障點(diǎn)已慢,因此它們對(duì)故障更有彈性曲聂。

例如,在我們的圖片服務(wù)器應(yīng)用程序中,所有圖片會(huì)在某處另一塊硬件冗余副本(理想情況下是在不同的地理位置,以防在數(shù)據(jù)中心發(fā)生災(zāi)難如地震或火災(zāi))佑惠,所有潛在的服務(wù)請(qǐng)求訪問圖片的服務(wù)訪問圖像也是冗余的朋腋。(請(qǐng)參見圖1.3)(負(fù)載平衡器是實(shí)現(xiàn)這一點(diǎn)的一種很好的方法,但是下面還有更多內(nèi)容)膜楷。

圖1.3:帶有冗余的圖像托管應(yīng)用程序

2.4 分區(qū)

可能有非常大的數(shù)據(jù)集無法安裝在單個(gè)服務(wù)器上乍丈。也可能是一個(gè)操作需要太多的計(jì)算資源,性能下降把将,需要增加容量轻专。無論哪種情況,你都有兩個(gè)選擇:垂直擴(kuò)展還是水平擴(kuò)展察蹲。

垂直擴(kuò)展意味著向單個(gè)服務(wù)器添加更多資源请垛。因此,對(duì)于非常大的數(shù)據(jù)集洽议,這可能意味著添加更多(或更大)的硬盤驅(qū)動(dòng)器宗收,以便單個(gè)服務(wù)器可以包含整個(gè)數(shù)據(jù)集。在計(jì)算操作的情況下亚兄,這可能意味著將計(jì)算轉(zhuǎn)移到具有更快CPU或更多內(nèi)存的更大的服務(wù)器上混稽。在每種情況下,垂直擴(kuò)展都是通過使單個(gè)資源能夠更多地獨(dú)立處理來實(shí)現(xiàn)的。

另一方面匈勋,水平擴(kuò)展就是添加更多的節(jié)點(diǎn)礼旅。在大數(shù)據(jù)集的情況下,可能是第二個(gè)服務(wù)器來存儲(chǔ)數(shù)據(jù)集的一部分洽洁,對(duì)于計(jì)算資源痘系,這意味著將操作或負(fù)載分散到一些額外的節(jié)點(diǎn)上。為了充分利用水平伸縮饿自,應(yīng)該將其作為系統(tǒng)體系結(jié)構(gòu)的一個(gè)內(nèi)在設(shè)計(jì)原則包含進(jìn)來汰翠,否則修改和分離上下文來實(shí)現(xiàn)這一點(diǎn)可能會(huì)非常麻煩。

當(dāng)涉及到水平擴(kuò)展時(shí)昭雌,最常見的技術(shù)之一是將服務(wù)劃分為分區(qū)或碎片复唤。這些分區(qū)可以是分布式的,以便每個(gè)邏輯功能集是獨(dú)立的烛卧;這可以通過地理邊界來實(shí)現(xiàn)苟穆,也可以通過其他標(biāo)準(zhǔn)來實(shí)現(xiàn),比如非付費(fèi)用戶和付費(fèi)用戶唱星。這些方案的優(yōu)點(diǎn)是雳旅,它們提供了具有附加容量的服務(wù)或數(shù)據(jù)存儲(chǔ)。

在我們的圖像服務(wù)器示例中间聊,用于存儲(chǔ)圖像的單個(gè)文件服務(wù)器可能被多個(gè)文件服務(wù)器替換攒盈,每個(gè)文件服務(wù)器都包含自己獨(dú)特的圖像集。(參見圖1.4)哎榴。這樣的體系結(jié)構(gòu)將允許系統(tǒng)用圖像填充每個(gè)文件服務(wù)器型豁,并在磁盤滿時(shí)添加額外的服務(wù)器。該設(shè)計(jì)需要一個(gè)命名方案尚蝌,將圖像的文件名綁定到包含它的服務(wù)器迎变。圖像的名稱可以由跨服務(wù)器映射的一致哈希方案形成∑裕或者衣形,可以為每個(gè)圖像分配一個(gè)增量ID,這樣當(dāng)客戶機(jī)請(qǐng)求一個(gè)圖像時(shí)姿鸿,圖像檢索服務(wù)只需要維護(hù)映射到每個(gè)服務(wù)器的ID范圍(比如索引)谆吴。

圖1.4:帶有冗余和分區(qū)的圖像托管應(yīng)用程序

當(dāng)然,跨多個(gè)服務(wù)器分發(fā)數(shù)據(jù)或功能也存在挑戰(zhàn)苛预。其中一個(gè)關(guān)鍵問題是數(shù)據(jù)局部性;在分布式系統(tǒng)中句狼,數(shù)據(jù)越接近操作或計(jì)算點(diǎn),系統(tǒng)的性能就越好热某。因此腻菇,將數(shù)據(jù)分散在多個(gè)服務(wù)器上可能存在問題胳螟,因?yàn)槿魏涡枰獢?shù)據(jù)的時(shí)候,數(shù)據(jù)都可能不是本地的筹吐,這迫使服務(wù)器在網(wǎng)絡(luò)上執(zhí)行代價(jià)高昂的獲取所需信息的操作糖耸。

另一個(gè)潛在的問題是不一致。當(dāng)從共享資源(可能是另一個(gè)服務(wù)或數(shù)據(jù)存儲(chǔ))讀取和寫入不同的服務(wù)時(shí)骏令,就有可能出現(xiàn)競(jìng)爭(zhēng)條件(某些數(shù)據(jù)應(yīng)該被更新,但讀取發(fā)生在更新之前)垄提,在這些情況下榔袋,數(shù)據(jù)是不一致的。例如铡俐,在圖像托管場(chǎng)景中凰兑,如果一個(gè)客戶端發(fā)送一個(gè)請(qǐng)求,要求用一個(gè)新標(biāo)題更新狗的圖像审丘,將其從“dog”更改為“Gizmo”吏够,但同時(shí)另一個(gè)客戶端正在讀取圖像,則可能發(fā)生競(jìng)爭(zhēng)情況滩报。在這種情況下锅知,不清楚第二個(gè)客戶將收到哪個(gè)標(biāo)題,“Dog”或“Gizmo”脓钾。

當(dāng)然售睹,分區(qū)數(shù)據(jù)存在一些障礙,但是分區(qū)允許將每個(gè)問題按照數(shù)據(jù)可训、負(fù)載昌妹、使用模式等分割為可管理的塊。這有助于提高可擴(kuò)展性和可管理性握截,但也不是沒有風(fēng)險(xiǎn)飞崖。有很多方法可以降低風(fēng)險(xiǎn)和處理失敗;但是,為了簡(jiǎn)潔起見谨胞,本章不討論這些問題固歪。

3. 快速和可擴(kuò)展數(shù)據(jù)訪問的構(gòu)建塊

在介紹了設(shè)計(jì)分布式系統(tǒng)時(shí)的一些核心考慮事項(xiàng)之后,現(xiàn)在讓我們討論比較困難的部分:擴(kuò)展對(duì)數(shù)據(jù)的訪問胯努。

大多數(shù)簡(jiǎn)單的web應(yīng)用程序昼牛,例如LAMP棧應(yīng)用程序,如圖1.5所示康聂。


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

隨著它們的增長(zhǎng)贰健,有兩個(gè)主要的挑戰(zhàn):擴(kuò)展對(duì)應(yīng)用服務(wù)器和數(shù)據(jù)庫(kù)的訪問。在高度可伸縮的應(yīng)用程序設(shè)計(jì)中恬汁,應(yīng)用程序(或web)服務(wù)器通常是最小化的伶椿,并且通常包含無共享的體系結(jié)構(gòu)辜伟。這使得系統(tǒng)的app服務(wù)器層可以水平伸縮。本設(shè)計(jì)的結(jié)果是將重物從棧下推到數(shù)據(jù)庫(kù)服務(wù)器和支持服務(wù)上脊另;正是在這一層导狡,真正的伸縮性和性能挑戰(zhàn)開始發(fā)揮作用。

本章的其余部分將專門討論一些更常見的策略和方法偎痛,通過提供對(duì)數(shù)據(jù)的快速訪問旱捧,使這些類型的服務(wù)快速且可伸縮。


圖1.6:過于簡(jiǎn)化的web應(yīng)用程序

大多數(shù)系統(tǒng)都可以過度簡(jiǎn)化為圖1.6踩麦。這是一個(gè)很好的開始枚赡。如果你有很多數(shù)據(jù),你想要快速便捷的訪問谓谦,就像在你桌子的最上面抽屜里放一盒糖果贫橙。雖然過于簡(jiǎn)化,但是前面的陳述暗示了兩個(gè)難題:存儲(chǔ)的可伸縮性和數(shù)據(jù)的快速訪問反粥。

對(duì)于本節(jié)卢肃,假設(shè)您有許多TB的數(shù)據(jù),并且希望允許用戶隨機(jī)訪問其中的一小部分?jǐn)?shù)據(jù)才顿。(參見圖1.7)莫湘。這類似于在圖像應(yīng)用程序示例中的文件服務(wù)器上定位一個(gè)圖像文件。

圖1.7:訪問特定數(shù)據(jù)

這尤其具有挑戰(zhàn)性郑气,因?yàn)閷讉€(gè)TB的數(shù)據(jù)加載到內(nèi)存中可能非常昂貴逊脯;這直接轉(zhuǎn)換為磁盤IO。從磁盤讀取要比從內(nèi)存讀取慢很多倍竣贪。對(duì)于大型數(shù)據(jù)集來說军洼,這種速度差異實(shí)際上是累積起來的;在實(shí)際數(shù)字中演怎,順序讀取的內(nèi)存訪問速度是磁盤讀取的6倍匕争,隨機(jī)讀取的內(nèi)存訪問速度是磁盤讀取的10萬倍。此外爷耀,即使使用惟一的id甘桑,要解決知道在何處查找少量數(shù)據(jù)的問題也是一項(xiàng)艱巨的任務(wù)。

值得慶幸的是歹叮,您可以使用許多選項(xiàng)來簡(jiǎn)化這一過程跑杭;其中比較重要的四個(gè)是緩存、代理咆耿、索引和負(fù)載平衡器德谅。本節(jié)的其余部分將討論如何使用這些概念使數(shù)據(jù)訪問更快。

3.1 緩存

緩存利用了引用原則的局部性:最近請(qǐng)求的數(shù)據(jù)可能會(huì)被再次請(qǐng)求萨螺。它們幾乎被用于計(jì)算的每一層:硬件窄做、操作系統(tǒng)愧驱、web瀏覽器、web應(yīng)用程序等等椭盏。緩存類似于短期內(nèi)存:它的空間有限组砚,但通常比原始數(shù)據(jù)源更快,并且包含最近訪問的項(xiàng)掏颊。緩存可以存在于體系結(jié)構(gòu)的所有級(jí)別糟红,但通常位于最接近前端的級(jí)別,在那里實(shí)現(xiàn)緩存可以快速返回?cái)?shù)據(jù)乌叶,而不會(huì)占用下游的級(jí)別盆偿。

在我們的API示例中,如何使用緩存加快數(shù)據(jù)訪問速度?在本例中枉昏,有兩個(gè)地方可以插入緩存陈肛。一個(gè)選項(xiàng)是在請(qǐng)求層節(jié)點(diǎn)上插入緩存揍鸟,如圖1.8所示兄裂。


圖1.8:在請(qǐng)求層節(jié)點(diǎn)上插入緩存

將緩存直接放置在請(qǐng)求層節(jié)點(diǎn)上可以實(shí)現(xiàn)響應(yīng)數(shù)據(jù)的本地存儲(chǔ)。每次向服務(wù)發(fā)出請(qǐng)求時(shí)阳藻,如果存在晰奖,節(jié)點(diǎn)將快速返回本地緩存的數(shù)據(jù)。如果不在緩存中腥泥,請(qǐng)求節(jié)點(diǎn)將從磁盤查詢數(shù)據(jù)匾南。一個(gè)請(qǐng)求層節(jié)點(diǎn)上的緩存也可以位于內(nèi)存(非常快)和節(jié)點(diǎn)的本地磁盤(比網(wǎng)絡(luò)存儲(chǔ)快)中蛔外。


圖1.9:多個(gè)緩存

當(dāng)把這個(gè)擴(kuò)展到很多節(jié)點(diǎn)時(shí)會(huì)發(fā)生什么蛆楞?正如圖1.9中所看到的,如果請(qǐng)求層擴(kuò)展到多個(gè)節(jié)點(diǎn)夹厌,那么每個(gè)節(jié)點(diǎn)仍然可以擁有自己的緩存豹爹。然而,如果負(fù)載均衡器在節(jié)點(diǎn)之間隨機(jī)分配請(qǐng)求矛纹,那么相同的請(qǐng)求將被發(fā)送到不同的節(jié)點(diǎn)臂聋,從而增加緩存丟失』蚰希克服這個(gè)障礙的兩個(gè)選擇是全局緩存和分布式緩存孩等。

3.2 全局緩存

全局緩存就像它聽起來的那樣:所有節(jié)點(diǎn)都使用相同的單個(gè)緩存空間。這涉及到添加服務(wù)器或某種類型的文件存儲(chǔ)采够,速度比原始存儲(chǔ)快肄方,并且所有請(qǐng)求層節(jié)點(diǎn)都可以訪問。每個(gè)請(qǐng)求節(jié)點(diǎn)以與本地節(jié)點(diǎn)相同的方式查詢緩存蹬癌。這種緩存方案可能有點(diǎn)復(fù)雜,因?yàn)樗苋菀妆谎蜎]當(dāng)客戶端和請(qǐng)求的數(shù)量增加劣砍,但在一些架構(gòu)中非常有效(特別是那些專門的硬件,使這個(gè)全局緩存非常快困后,或者有固定的數(shù)據(jù)集需要緩存)惜论。

下面兩圖描述了兩種常見的全局緩存形式。在圖1.10中聚谁,當(dāng)緩存中沒有找到緩存響應(yīng)時(shí),緩存本身將負(fù)責(zé)從相應(yīng)的存儲(chǔ)中檢索缺失的數(shù)據(jù)塊。在圖1.11中洲炊,請(qǐng)求節(jié)點(diǎn)負(fù)責(zé)檢索緩存中沒有找到的任何數(shù)據(jù)。


圖1.10:全局緩存尼啡,其中緩存負(fù)責(zé)檢索
圖1.11:全局緩存暂衡,其中請(qǐng)求節(jié)點(diǎn)負(fù)責(zé)檢索

大多數(shù)利用全局緩存的應(yīng)用程序傾向于使用第一種類型,其中緩存本身管理清除和獲取數(shù)據(jù)崖瞭,以防止客戶機(jī)對(duì)相同數(shù)據(jù)的大量請(qǐng)求狂巢。然而,在某些情況下书聚,第二個(gè)實(shí)現(xiàn)更有意義唧领。例如,如果緩存用于非常大的文件雌续,那么低的緩存命中率將導(dǎo)致緩存緩沖區(qū)被緩存丟失所淹沒斩个;在這種情況下,在緩存中保存大量的總數(shù)據(jù)集(或熱數(shù)據(jù)集)是有幫助的驯杜。另一個(gè)例子是一個(gè)架構(gòu)受啥,其中緩存中存儲(chǔ)的文件是靜態(tài)的,不應(yīng)該被刪除鸽心。(這可能是因?yàn)閼?yīng)用程序?qū)?shù)據(jù)延遲的需求—對(duì)于大型數(shù)據(jù)集滚局,某些數(shù)據(jù)塊可能需要非常快—在這種情況下顽频,應(yīng)用程序邏輯比緩存更好地理解清除策略或熱點(diǎn)藤肢。)

3.3 分布式緩存

在一個(gè)分布式緩存(圖1.12),它的每個(gè)節(jié)點(diǎn)緩存數(shù)據(jù)的一部分冲九,所以如果冰箱作為雜貨店的緩存谤草,分布式緩存就像把你的食物在幾個(gè)位置--你的冰箱、櫥柜莺奸,和午餐盒--方便的位置獲取零食丑孩,沒有去商店。通常灭贷,緩存使用一致的哈希函數(shù)進(jìn)行劃分温学,這樣,如果請(qǐng)求節(jié)點(diǎn)正在尋找某段數(shù)據(jù)甚疟,它可以快速知道在分布式緩存中何處查找仗岖,以確定該數(shù)據(jù)是否可用逃延。在本例中,每個(gè)節(jié)點(diǎn)都有一小部分緩存轧拄,在向源節(jié)點(diǎn)發(fā)送數(shù)據(jù)請(qǐng)求之前揽祥,將向一個(gè)緩存節(jié)點(diǎn)發(fā)送數(shù)據(jù)請(qǐng)求。因此檩电,分布式緩存的優(yōu)點(diǎn)之一是增加了緩存空間拄丰,只需要向請(qǐng)求池添加節(jié)點(diǎn)即可。

分布式緩存的一個(gè)缺點(diǎn)是修復(fù)丟失的節(jié)點(diǎn)俐末。一些分布式緩存通過在不同的節(jié)點(diǎn)上存儲(chǔ)數(shù)據(jù)的多個(gè)副本來解決這個(gè)問題料按;但是,您可以想象這種邏輯如何快速變得復(fù)雜卓箫,尤其是在從請(qǐng)求層添加或刪除節(jié)點(diǎn)時(shí)载矿。盡管即使節(jié)點(diǎn)消失并且部分緩存丟失,請(qǐng)求也只會(huì)從源文件中拉出—所以這并不一定是災(zāi)難性的!


圖1.12:分布式緩存

緩存的好處是烹卒,它們通常使事情更快(當(dāng)然是正確實(shí)現(xiàn)的!)你選擇的方法只允許你更快地處理更多的請(qǐng)求闷盔。然而,所有這些緩存的代價(jià)是必須維護(hù)額外的存儲(chǔ)空間甫题,通常以昂貴的內(nèi)存的形式出現(xiàn)馁筐;沒有什么是免費(fèi)的涂召。緩存對(duì)于提高速度非常有用坠非,而且在高負(fù)載條件下提供系統(tǒng)功能,否則將導(dǎo)致服務(wù)完全降級(jí)果正。

流行的開源緩存的一個(gè)例子是Memcached (http://memcached.org/)(它既可以作為本地緩存炎码,也可以作為分布式緩存);然而秋泳,還有許多其他選項(xiàng)(包括許多特定于語言或框架的選項(xiàng))潦闲。

Memcached用于許多大型web站點(diǎn),盡管它非常強(qiáng)大迫皱,但它只是內(nèi)存中的鍵值存儲(chǔ)歉闰,針對(duì)任意數(shù)據(jù)存儲(chǔ)和快速查找進(jìn)行了優(yōu)化(O(1))。

Facebook使用幾種不同類型的緩存來獲得站點(diǎn)性能卓起。它們?cè)谡Z言級(jí)別使用$GLOBALS和APC緩存(以函數(shù)調(diào)用為代價(jià)在PHP中提供)和敬,這有助于更快地進(jìn)行中間函數(shù)調(diào)用和結(jié)果。(大多數(shù)語言都有這些類型的庫(kù)來提高web頁(yè)面性能戏阅,而且?guī)缀蹩偸菓?yīng)該使用它們昼弟。) 然后,F(xiàn)acebook使用一個(gè)分布在多個(gè)服務(wù)器上的全局緩存奕筐,這樣一個(gè)訪問緩存的函數(shù)調(diào)用就可以同時(shí)發(fā)出多個(gè)請(qǐng)求舱痘,以獲取存儲(chǔ)在不同memcached服務(wù)器上的數(shù)據(jù)变骡。這使它們能夠?yàn)橛脩粜畔?shù)據(jù)獲得更高的性能和吞吐量,并擁有一個(gè)更新數(shù)據(jù)的中心位置(這很重要芭逝,因?yàn)楫?dāng)您運(yùn)行數(shù)千臺(tái)服務(wù)器時(shí)塌碌,緩存失效和維護(hù)一致性可能會(huì)很有挑戰(zhàn)性)。

現(xiàn)在讓我們討論一下當(dāng)數(shù)據(jù)不在緩存中時(shí)該做什么……

3.4 代理

在基本級(jí)別上旬盯,代理服務(wù)器是接收來自客戶機(jī)的請(qǐng)求并將其轉(zhuǎn)發(fā)到后端源服務(wù)器的中間硬件/軟件誊爹。通常,代理用于過濾請(qǐng)求瓢捉、日志請(qǐng)求频丘,有時(shí)還用于轉(zhuǎn)換請(qǐng)求(通過添加/刪除頭、加密/解密或壓縮)泡态。


圖1.13:代理服務(wù)

代理在協(xié)調(diào)來自多個(gè)服務(wù)器的請(qǐng)求時(shí)也非常有用搂漠,提供了從系統(tǒng)范圍的角度優(yōu)化請(qǐng)求流量的機(jī)會(huì)。使用代理加速數(shù)據(jù)訪問的一種方法是將相同(或類似)請(qǐng)求合并為一個(gè)請(qǐng)求某弦,然后將單個(gè)結(jié)果返回給請(qǐng)求客戶機(jī)桐汤。這就是所謂的折疊轉(zhuǎn)發(fā)。

假設(shè)有一個(gè)跨多個(gè)節(jié)點(diǎn)的對(duì)相同數(shù)據(jù)的請(qǐng)求(我們稱之為littleB)靶壮,而該數(shù)據(jù)塊不在緩存中怔毛。如果將該請(qǐng)求路由到代理,那么所有這些請(qǐng)求都可以分解為一個(gè)請(qǐng)求腾降,這意味著我們只需從磁盤中讀取一次littleB拣度。(參見圖1.14)。這種設(shè)計(jì)會(huì)帶來一些成本螃壤,因?yàn)槊總€(gè)請(qǐng)求可能會(huì)有稍微高的延遲抗果,有些請(qǐng)求可能會(huì)稍微延遲,以便與類似的請(qǐng)求分組奸晴。但是在高負(fù)載的情況下冤馏,它將提高性能,特別是在反復(fù)請(qǐng)求相同的數(shù)據(jù)時(shí)寄啼。這類似于緩存逮光,但它不是像緩存那樣存儲(chǔ)數(shù)據(jù)/文檔,而是優(yōu)化這些文檔的請(qǐng)求或調(diào)用墩划,并充當(dāng)這些客戶機(jī)的代理涕刚。

例如,在LAN代理中走诞,客戶端不需要自己的ip連接到Internet, LAN將折疊來自客戶端對(duì)相同內(nèi)容的調(diào)用副女。這里很容易混淆,因?yàn)樵S多代理也是緩存(因?yàn)樗欠胖镁彺娴倪壿嬑恢?,但是并不是所有緩存都充當(dāng)代理碑幅。


圖1.14:使用代理服務(wù)器折疊請(qǐng)求

使用代理的另一種好方法不僅是折疊相同數(shù)據(jù)的請(qǐng)求戴陡,還可以折疊源存儲(chǔ)中空間上相鄰的數(shù)據(jù)的請(qǐng)求(連續(xù)存儲(chǔ)在磁盤上)。使用這種策略可以最大化請(qǐng)求的數(shù)據(jù)局部性沟涨,從而降低請(qǐng)求延遲恤批。例如,假設(shè)一堆節(jié)點(diǎn)請(qǐng)求B的部件:partB1裹赴、partB2等喜庞。我們可以設(shè)置代理來識(shí)別單個(gè)請(qǐng)求的空間位置,將它們折疊成單個(gè)請(qǐng)求并只返回bigB棋返,從而極大地減少對(duì)數(shù)據(jù)源的讀取延都。(參見圖1.15)。當(dāng)您隨機(jī)訪問TB級(jí)數(shù)據(jù)時(shí)睛竣,這將在請(qǐng)求時(shí)間上產(chǎn)生非常大的差異晰房!代理在高負(fù)載的情況下,或者在緩存有限的情況下尤其有用射沟,因?yàn)樗鼈儽举|(zhì)上可以將多個(gè)請(qǐng)求批處理為一個(gè)請(qǐng)求殊者。


圖1.15:使用代理折疊空間上緊密相連的數(shù)據(jù)請(qǐng)求

值得注意的是,您可以同時(shí)使用代理和緩存验夯,但是通常最好將緩存放在代理前面猖吴,這與在擁擠的馬拉松比賽中讓跑得更快的人先開始是相同的道理。這是因?yàn)榫彺媸菫閮?nèi)存中的數(shù)據(jù)提供服務(wù)的挥转,它非澈1危快,并且不介意對(duì)同一個(gè)結(jié)果的多個(gè)請(qǐng)求扁位。但是准潭,如果緩存位于代理服務(wù)器的另一端趁俊,那么緩存之前的每個(gè)請(qǐng)求都會(huì)有額外的延遲域仇,這可能會(huì)影響性能。

如果你正在考慮將代理添加到系統(tǒng)中寺擂,有許多選項(xiàng)可以考慮暇务;SquidVarnish都經(jīng)過測(cè)試,并在許多生產(chǎn)網(wǎng)站上廣泛使用怔软。這些代理解決方案提供了許多優(yōu)化垦细,以充分利用客戶機(jī)-服務(wù)器通信。在web服務(wù)器層將其中之一安裝為反向代理(在下面的負(fù)載平衡器一節(jié)中進(jìn)行了解釋)可以顯著提高web服務(wù)器性能挡逼,減少處理傳入客戶機(jī)請(qǐng)求所需的工作量括改。

3.5 索引

使用索引快速訪問數(shù)據(jù)是優(yōu)化數(shù)據(jù)訪問性能的著名策略;可能是數(shù)據(jù)庫(kù)中最著名的名詞家坎。索引可以在增加的存儲(chǔ)開銷和較慢的寫操作之間進(jìn)行權(quán)衡(因?yàn)楸仨毻瑫r(shí)寫數(shù)據(jù)和更新索引)嘱能,以獲得更快的讀取速度吝梅。

與傳統(tǒng)的關(guān)系數(shù)據(jù)存儲(chǔ)一樣,您也可以將此概念應(yīng)用于更大的數(shù)據(jù)集惹骂。索引的訣竅在于苏携,您必須仔細(xì)考慮用戶將如何訪問您的數(shù)據(jù)。在數(shù)據(jù)集有很多TBs大小对粪,但是有效負(fù)載非常小(例如右冻,1kb)的情況下,索引是優(yōu)化數(shù)據(jù)訪問的必要條件著拭。在這么大的數(shù)據(jù)集中找到一個(gè)小的有效負(fù)載可能是一個(gè)真正的挑戰(zhàn)纱扭,因?yàn)槟豢赡茉谌魏魏侠淼臅r(shí)間內(nèi)遍歷那么多數(shù)據(jù)。此外儡遮,如此大的數(shù)據(jù)集很可能分布在多個(gè)(或多個(gè))物理設(shè)備上—這意味著您需要某種方法來找到所需數(shù)據(jù)的正確物理位置跪但。索引是最好的方法。


圖1.16:索引

索引可以像目錄表一樣使用峦萎,將你引向數(shù)據(jù)所在的位置屡久。例如,假設(shè)你正在尋找一段數(shù)據(jù)(B的part 2)爱榔,你如何知道在哪里可以找到它被环?如果你有一個(gè)按數(shù)據(jù)類型排序的索引—比如數(shù)據(jù)A、B详幽、C—它將告訴你數(shù)據(jù)B在原點(diǎn)的位置筛欢。然后你只需要找到那個(gè)位置,讀你想讀的B部分唇聘。(參見圖1.16)版姑。

這些索引通常存儲(chǔ)在內(nèi)存中,或者對(duì)傳入的客戶機(jī)請(qǐng)求非常鄰近的某個(gè)地方迟郎。Berkeley DBs (BDBs)和樹狀數(shù)據(jù)結(jié)構(gòu)通常用于將數(shù)據(jù)存儲(chǔ)在有序列表中剥险,非常適合使用索引訪問。

通常有許多層索引充當(dāng)映射宪肖,將你從一個(gè)位置移動(dòng)到下一個(gè)位置表制,等等,直到你獲得所需的特定數(shù)據(jù)控乾。(參見圖1.17)么介。


圖1.17:多個(gè)索引層

索引還可以用于創(chuàng)建相同數(shù)據(jù)的多個(gè)不同視圖。對(duì)于大型數(shù)據(jù)集蜕衡,這是一種定義不同篩選器和排序的好方法壤短,無需創(chuàng)建許多額外的數(shù)據(jù)副本。

例如,假設(shè)前面的圖像托管系統(tǒng)實(shí)際上托管圖書頁(yè)面的圖像久脯,并且該服務(wù)允許客戶端跨這些圖像中的文本進(jìn)行查詢蒜绽,搜索關(guān)于某個(gè)主題的所有圖書內(nèi)容,與搜索引擎允許搜索HTML內(nèi)容的方式相同桶现。在這種情況下躲雅,所有這些圖書圖像都需要許多服務(wù)器來存儲(chǔ)文件,找到一個(gè)頁(yè)面呈現(xiàn)給用戶可能有點(diǎn)麻煩骡和。首先相赁,查詢?nèi)我鈫卧~和單詞元組的反向索引需要易于訪問;接下來的挑戰(zhàn)是導(dǎo)航到書中的準(zhǔn)確頁(yè)面和位置慰于,并為結(jié)果檢索正確的圖像钮科。因此,在本例中婆赠,反向索引將映射到一個(gè)位置(例如book B)绵脯,然后B可能包含一個(gè)索引,其中包含每個(gè)部分中出現(xiàn)的所有單詞休里、位置和次數(shù)蛆挫。

反向索引(可以在上面的圖中表示Index1)可能如下所示—每個(gè)單詞或單詞元組提供書籍包含它們的索引。

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

中間索引看起來類似妙黍,但是只包含book b的單詞悴侵、位置和信息。這種嵌套索引體系結(jié)構(gòu)允許每個(gè)索引占用的空間比所有這些信息都必須存儲(chǔ)在一個(gè)大的反向索引中少拭嫁。

這在大型系統(tǒng)中是關(guān)鍵可免,因?yàn)榧词箟嚎s,這些索引也會(huì)變得非常大做粤,而且存儲(chǔ)起來非常昂貴浇借。在這個(gè)系統(tǒng)中,如果我們假設(shè)世界上有很多書—1億本---而且每本書只有10頁(yè)長(zhǎng)(為了簡(jiǎn)化計(jì)算)怕品,每頁(yè)250個(gè)單詞妇垢,這意味著有2500億個(gè)單詞。如果我們假設(shè)每個(gè)單詞平均有5個(gè)字符堵泽,每個(gè)字符占用8位(或1個(gè)字節(jié)修己,即使有些字符是2字節(jié)),那么每個(gè)單詞占用5個(gè)字節(jié)迎罗,那么一個(gè)只包含每個(gè)單詞一次的索引就超過了1tb的存儲(chǔ)空間。因此片仿,你可以看到纹安,創(chuàng)建包含許多其他信息的索引(比如單詞元組、數(shù)據(jù)位置和出現(xiàn)次數(shù))可以非常快地累加起來厢岂。

創(chuàng)建這些中間索引并將數(shù)據(jù)表示為更小的部分光督,使得大數(shù)據(jù)問題易于處理。數(shù)據(jù)可以分布在許多服務(wù)器上塔粒,并且仍然可以快速訪問结借。索引是信息檢索的基石,也是當(dāng)今現(xiàn)代搜索引擎的基礎(chǔ)卒茬。當(dāng)然船老,這一節(jié)只觸及了表面,關(guān)于如何使索引更小圃酵、更快柳畔、包含更多信息(比如相關(guān)性)和無縫更新,還有很多研究正在進(jìn)行中郭赐。(競(jìng)爭(zhēng)條件和添加新數(shù)據(jù)或更改現(xiàn)有數(shù)據(jù)所需的更新數(shù)量都存在一些可管理性挑戰(zhàn)薪韩,特別是在涉及相關(guān)性或得分的事件中)。

能夠快速捌锭、輕松地找到你的數(shù)據(jù)是很重要的俘陷;索引是實(shí)現(xiàn)這一目標(biāo)的有效而簡(jiǎn)單的工具。

3.6 負(fù)載均衡器

最后观谦,任何分布式系統(tǒng)的另一個(gè)關(guān)鍵部分是負(fù)載均衡器岭洲。負(fù)載均衡器是任何體系結(jié)構(gòu)的主要部分,因?yàn)樗鼈兊慕巧窃谪?fù)責(zé)服務(wù)請(qǐng)求的一組節(jié)點(diǎn)之間分配負(fù)載坎匿。這允許多個(gè)節(jié)點(diǎn)透明地為系統(tǒng)中的相同功能提供服務(wù)盾剩。(參見圖1.18)。它們的主要目的是處理大量的并發(fā)連接替蔬,并將這些連接路由到一個(gè)請(qǐng)求節(jié)點(diǎn)告私,從而允許系統(tǒng)通過添加節(jié)點(diǎn)擴(kuò)展來處理更多的請(qǐng)求。


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

可以使用許多不同的算法來為請(qǐng)求提供服務(wù)承桥,包括隨機(jī)選擇節(jié)點(diǎn)驻粟、輪詢,甚至根據(jù)特定的標(biāo)準(zhǔn)(如內(nèi)存或CPU利用率)選擇節(jié)點(diǎn)凶异。負(fù)載均衡器可以實(shí)現(xiàn)為軟件或硬件設(shè)備蜀撑。一個(gè)被廣泛采用的開源軟件負(fù)載均衡器是HAProxy)。

在分布式系統(tǒng)中剩彬,負(fù)載均衡器通常位于系統(tǒng)的最前端酷麦,因此所有傳入的請(qǐng)求都會(huì)相應(yīng)地路由。在復(fù)雜的分布式系統(tǒng)中喉恋,請(qǐng)求路由到多個(gè)負(fù)載平衡器的情況并不少見沃饶,如圖1.19所示母廷。


圖1.19:多個(gè)負(fù)載均衡器

與代理一樣,一些負(fù)載均衡器也可以根據(jù)請(qǐng)求的類型以不同的方式路由請(qǐng)求糊肤。(從技術(shù)上講琴昆,這些也稱為反向代理。)

負(fù)載均衡器面臨的挑戰(zhàn)之一是管理特定于用戶會(huì)話的數(shù)據(jù)馆揉。在一個(gè)電子商務(wù)網(wǎng)站业舍,當(dāng)你只有一個(gè)客戶端很容易允許用戶把東西放在購(gòu)物車和保存這些內(nèi)容之間的訪問(這是很重要的,因?yàn)楫?dāng)顧客返回時(shí)如果這些商品仍然在他們的購(gòu)物車中升酣,你更有可能賣出這些商品)舷暮。但是,如果用戶被路由到一個(gè)節(jié)點(diǎn)進(jìn)行會(huì)話拗踢,然后在下次訪問時(shí)路由到另一個(gè)節(jié)點(diǎn)脚牍,則可能會(huì)出現(xiàn)不一致性,因?yàn)樾鹿?jié)點(diǎn)可能丟失了該用戶的購(gòu)物車內(nèi)容巢墅。(如果你在購(gòu)物車?yán)锓帕?包山露水诸狭,然后回來發(fā)現(xiàn)里面是空的,你會(huì)高興嗎?)君纫。解決這個(gè)問題的一種方法是使會(huì)話具有粘性驯遇,以便用戶總是路由到相同的節(jié)點(diǎn),但是這樣就很難利用一些可靠性特性蓄髓,比如自動(dòng)故障轉(zhuǎn)移叉庐。在這種情況下,用戶的購(gòu)物車總是有內(nèi)容会喝,但是如果他們的粘性節(jié)點(diǎn)不可用陡叠,那么就需要有一個(gè)特殊的情況,并且假設(shè)在其中的內(nèi)容將不再有效(盡管希望這個(gè)假設(shè)不會(huì)構(gòu)建到應(yīng)用程序中)肢执。當(dāng)然枉阵,這個(gè)問題可以使用本章中的其他策略和工具來解決,比如服務(wù)预茄,以及許多沒有涉及到的(比如瀏覽器緩存兴溜、cookie和URL重寫)。

如果一個(gè)系統(tǒng)只有幾個(gè)節(jié)點(diǎn)耻陕,那么像輪詢DNS這樣的系統(tǒng)可能更有意義拙徽,因?yàn)樨?fù)載均衡器可能很昂貴,并且增加了不必要的復(fù)雜性诗宣。當(dāng)然膘怕,在較大的系統(tǒng)中有各種不同的調(diào)度和負(fù)載均衡算法,包括簡(jiǎn)單的隨機(jī)選擇或循環(huán)調(diào)度算法梧田,以及考慮利用率和容量等因素的更復(fù)雜的機(jī)制淳蔼。所有這些算法都允許分發(fā)流量和請(qǐng)求侧蘸,并且可以提供有用的可靠性工具裁眯,比如自動(dòng)故障轉(zhuǎn)移或自動(dòng)刪除壞節(jié)點(diǎn)(比如當(dāng)它變得無響應(yīng)時(shí))鹉梨。然而,這些高級(jí)特性會(huì)使問題診斷變得很麻煩穿稳。例如存皂,在高負(fù)載情況下,負(fù)載平衡器將刪除可能很慢或超時(shí)的節(jié)點(diǎn)(由于請(qǐng)求太多)逢艘,但這只會(huì)加劇其他節(jié)點(diǎn)的情況旦袋。在這些情況下,廣泛的監(jiān)測(cè)是很重要的它改,因?yàn)榭傮w系統(tǒng)流量和吞吐量可能看起來在下降(因?yàn)楣?jié)點(diǎn)服務(wù)的請(qǐng)求更少)疤孕,但是單個(gè)節(jié)點(diǎn)已經(jīng)達(dá)到最大。

負(fù)載平衡器是一種允許你擴(kuò)展系統(tǒng)容量的簡(jiǎn)單方法央拖,與本文中的其他技術(shù)一樣祭阀,它在分布式系統(tǒng)體系結(jié)構(gòu)中扮演著重要角色。負(fù)載均衡器還提供了能夠測(cè)試節(jié)點(diǎn)健康狀況的關(guān)鍵功能鲜戒,這樣专控,如果一個(gè)節(jié)點(diǎn)沒有響應(yīng)或負(fù)載過重,就可以從處理請(qǐng)求的池中刪除它遏餐,從而利用系統(tǒng)中不同節(jié)點(diǎn)的冗余伦腐。

3.7 隊(duì)列

到目前為止,我們已經(jīng)介紹了許多快速讀取數(shù)據(jù)的方法失都,但是擴(kuò)展數(shù)據(jù)層的另一個(gè)重要部分是有效地管理寫操作柏蘑。當(dāng)系統(tǒng)很簡(jiǎn)單,處理負(fù)載很小粹庞,數(shù)據(jù)庫(kù)很小時(shí)咳焚,寫操作的速度可以預(yù)見;然而信粮,在更復(fù)雜的系統(tǒng)中黔攒,寫操作幾乎要花費(fèi)很長(zhǎng)時(shí)間。例如强缘,數(shù)據(jù)可能必須寫在不同服務(wù)器或索引的多個(gè)位置督惰,或者系統(tǒng)可能只是處于高負(fù)載下。在寫操作或任何相關(guān)任務(wù)可能需要很長(zhǎng)時(shí)間的情況下旅掂,實(shí)現(xiàn)性能和可用性需要在系統(tǒng)中構(gòu)建異步性赏胚;一種常見的方法是使用隊(duì)列。


圖1.20:同步請(qǐng)求

設(shè)想一個(gè)系統(tǒng)商虐,其中每個(gè)客戶端都請(qǐng)求一個(gè)任務(wù)進(jìn)行遠(yuǎn)程服務(wù)觉阅。這些客戶機(jī)中的每一個(gè)都將其請(qǐng)求發(fā)送到服務(wù)器崖疤,服務(wù)器在服務(wù)器上盡可能快地完成任務(wù)并將結(jié)果返回給各自的客戶機(jī)。在小型系統(tǒng)中典勇,一臺(tái)服務(wù)器(或邏輯服務(wù))可以像傳入客戶一端樣快速地為它們提供服務(wù)劫哼,這種情況應(yīng)該可以很好地工作。然而割笙,當(dāng)服務(wù)器接收到超過其處理能力的請(qǐng)求時(shí)权烧,每個(gè)客戶機(jī)都必須等待其他客戶機(jī)的請(qǐng)求完成后才能生成響應(yīng)。這是一個(gè)同步請(qǐng)求的例子伤溉,如圖1.20所示般码。這種同步行為會(huì)嚴(yán)重降低客戶端性能;客戶端被迫等待乱顾,直到它的請(qǐng)求得到響應(yīng)板祝。增加額外的服務(wù)器來處理系統(tǒng)負(fù)載也不能解決這個(gè)問題;即使有了有效的負(fù)載平衡走净,也很難確保實(shí)現(xiàn)最大化客戶性能所需的工作的均勻和公平分配券时。此外,如果處理請(qǐng)求的服務(wù)器不可用或失敗温技,則上游客戶機(jī)也會(huì)失敗革为。有效地解決這個(gè)問題需要在客戶端請(qǐng)求和為其提供服務(wù)的實(shí)際工作之間進(jìn)行抽象。


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

輸入隊(duì)列舵鳞。隊(duì)列聽起來很簡(jiǎn)單:一個(gè)任務(wù)進(jìn)入隊(duì)列震檩,被添加到隊(duì)列中,然后工作人員在他們有能力處理下一個(gè)任務(wù)時(shí)接手它蜓堕。(參見圖1.21)抛虏。這些任務(wù)可以表示對(duì)數(shù)據(jù)庫(kù)的簡(jiǎn)單寫入,也可以表示為文檔生成縮略圖預(yù)覽圖像這樣復(fù)雜的操作套才。當(dāng)客戶端向隊(duì)列提交任務(wù)請(qǐng)求時(shí)迂猴,他們不再被迫等待結(jié)果;相反背伴,他們只需要確認(rèn)請(qǐng)求已正確接收沸毁。當(dāng)客戶機(jī)需要時(shí),這個(gè)確認(rèn)稍后可以作為工作結(jié)果的參考傻寂。

隊(duì)列使客戶機(jī)能夠以異步方式工作息尺,提供了客戶機(jī)請(qǐng)求及其響應(yīng)的策略抽象。另一方面疾掰,在同步系統(tǒng)中搂誉,請(qǐng)求和應(yīng)答之間沒有區(qū)別,因此不能單獨(dú)管理它們静檬。在異步系統(tǒng)中炭懊,客戶端請(qǐng)求一個(gè)任務(wù)并级,服務(wù)用一條確認(rèn)任務(wù)已接收到的消息進(jìn)行響應(yīng),然后客戶端可以定期檢查任務(wù)的狀態(tài)侮腹,只在任務(wù)完成后請(qǐng)求結(jié)果嘲碧。當(dāng)客戶機(jī)等待異步請(qǐng)求完成時(shí),它可以自由地執(zhí)行其他工作凯旋,甚至可以對(duì)其他服務(wù)發(fā)出異步請(qǐng)求呀潭。后者是分布式系統(tǒng)中如何利用隊(duì)列和消息的一個(gè)例子钉迷。

隊(duì)列還提供了一些防止服務(wù)中斷和故障的保護(hù)至非。例如,創(chuàng)建一個(gè)高度健壯的隊(duì)列非常容易糠聪,它可以重試由于臨時(shí)服務(wù)器故障而失敗的服務(wù)請(qǐng)求荒椭。使用隊(duì)列執(zhí)行服務(wù)的質(zhì)量保證比直接將客戶端暴露給間歇性服務(wù)中斷要好得多,后者需要復(fù)雜且常常不一致的客戶端錯(cuò)誤處理舰蟆。

隊(duì)列是管理任何大型分布式系統(tǒng)的不同部分之間的分布式通信的基礎(chǔ)趣惠,有很多方法可以實(shí)現(xiàn)它們。有相當(dāng)多的開源隊(duì)列身害,如RabbitMQ味悄、ActiveMQ、BeanstalkD塌鸯,但也有一些使用Zookeeper等服務(wù)侍瑟,甚至使用Redis等數(shù)據(jù)存儲(chǔ)。

4. 結(jié)論

設(shè)計(jì)能夠快速訪問大量數(shù)據(jù)的高效系統(tǒng)是令人興奮的丙猬,而且有許多優(yōu)秀的工具可以支持各種新應(yīng)用程序涨颜。這一章只涉及了幾個(gè)例子,僅僅觸及了表面茧球,但是還有很多庭瑰,而且在這個(gè)領(lǐng)域還會(huì)有更多的創(chuàng)新。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末抢埋,一起剝皮案震驚了整個(gè)濱河市弹灭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌揪垄,老刑警劉巖穷吮,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異福侈,居然都是意外死亡酒来,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門肪凛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堰汉,“玉大人辽社,你說我怎么就攤上這事∏萄迹” “怎么了滴铅?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)就乓。 經(jīng)常有香客問我汉匙,道長(zhǎng),這世上最難降的妖魔是什么生蚁? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任噩翠,我火速辦了婚禮,結(jié)果婚禮上邦投,老公的妹妹穿的比我還像新娘伤锚。我一直安慰自己,他們只是感情好志衣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布屯援。 她就那樣靜靜地躺著,像睡著了一般念脯。 火紅的嫁衣襯著肌膚如雪狞洋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天绿店,我揣著相機(jī)與錄音吉懊,去河邊找鬼。 笑死惯吕,一個(gè)胖子當(dāng)著我的面吹牛惕它,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播废登,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼淹魄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了堡距?” 一聲冷哼從身側(cè)響起甲锡,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎羽戒,沒想到半個(gè)月后缤沦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡易稠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年缸废,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡企量,死狀恐怖测萎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情届巩,我是刑警寧澤硅瞧,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站恕汇,受9級(jí)特大地震影響腕唧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瘾英,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一枣接、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧方咆,春花似錦月腋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)片拍。三九已至煌集,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捌省,已是汗流浹背苫纤。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纲缓,地道東北人卷拘。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像祝高,于是被迫代替她去往敵國(guó)和親栗弟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容