主頁 > 軟體設計 > 系統設計:從零用戶擴展到百萬用戶

系統設計:從零用戶擴展到百萬用戶

2023-05-29 09:02:21 軟體設計

設計一個支持百萬用戶的系統是具有挑戰性的,這是一段需要不斷改進和不斷提升的旅程,在本章中,我們將構建一個支持單個用戶的系統,并逐漸擴展以服務于數百萬用戶,閱讀本章后,您將掌握一些技巧,幫助您解決系統設計面試問題,

AI不會取代你,使用AI的人會,歡迎關注我的公眾號:更AI,以程式員的視角來看AI能帶給我們什么~

單服務器設定

千里之行始于足下,構建一個復雜的系統也是如此,為了從簡單的東西開始,我們將所有內容都運行在一個單獨的服務器上,圖1顯示了一個單服務器設定的示意圖,其中所有內容都在一個服務器上運行:Web應用程式、資料庫、快取等,

image

為了理解這個設定,有助于調查請求流程和流量來源,讓我們首先看一下請求流程(圖1-2),

image

  1. 用戶通過域名訪問網站,例如api.mysite.com,通常,域名系統(DNS)是由第三方提供的付費服務,而不是由我們的服務器托管,
  2. Internet協議(IP)地址回傳給瀏覽器或移動應用,在本例中,回傳的IP地址是15.125.23.214,
  3. 一旦獲得IP地址,超文本傳輸協議(HTTP)[1]請求將直接發送到您的Web服務器,
  4. Web服務器回傳HTML頁面或JSON回應進行渲染,

接下來,讓我們來看一下流量來源,流向您的Web服務器的流量來自兩個來源:Web應用程式和移動應用程式,

  • Web應用程式:它使用一組服務器端語言(Java、Python等)來處理業務邏輯、存盤等,以及客戶端語言(HTML和JavaScript)來進行展示,
  • 移動應用程式:HTTP協議是移動應用程式與Web服務器之間的通信協議,由于其簡單性,JavaScript物件表示法(JSON)通常用于傳輸資料的API回應格式,下面是一個以JSON格式顯示的API回應示例:

GET /users/12 – 檢索id為12的用戶物件

image

資料庫

隨著用戶群體的增長,一個服務器已經不夠用了,我們需要多臺服務器:一臺用于處理網站和移動端的流量,另一臺用于資料庫(圖1-3),將網站和移動端流量(Web層)與資料庫(資料層)服務器分離,可以使它們能夠獨立擴展,

image

使用哪種資料庫?

您可以選擇傳統關系型資料庫或非關系型資料庫,讓我們來看看它們的區別,

關系型資料庫也被稱為關系資料庫管理系統(RDBMS)或SQL資料庫,最流行的有MySQL、Oracle資料庫、PostgreSQL等,關系型資料庫使用表和行來表示和存盤資料,您可以使用SQL在不同的資料庫表之間執行聯接操作,

非關系型資料庫也被稱為NoSQL資料庫,流行的有CouchDB、Neo4j、Cassandra、HBase、Amazon DynamoDB等[2],這些資料庫分為四類:鍵值存盤、圖存盤、列存盤和檔案存盤,非關系型資料庫通常不支持聯接操作,

對于大多數開發者來說,關系型資料庫是最佳選擇,因為它們已經存在了40多年,并且在歷史上表現良好,然而,如果關系型資料庫不適合您特定的使用情況,探索超越關系型資料庫是至關重要的,如果滿足以下情況,非關系型資料庫可能是正確的選擇:

  • 您的應用程式需要超低的延遲,
  • 您的資料是非結構化的,或者您沒有任何關系資料,
  • 您只需要對資料進行序列化和反序列化(JSON、XML、YAML等),
  • 您需要存盤大量的資料,

垂直擴展與水平擴展

垂直擴展,也稱為“縱向擴展”,是指向服務器添加更多的處理能力(CPU、RAM等)的程序,水平擴展,也稱為“橫向擴展”,允許您通過向資源池中添加更多的服務器來進行擴展,

當流量較低時,垂直擴展是一個很好的選擇,垂直擴展的簡單性是其主要優點,不幸的是,它也存在一些嚴重的局限性,

  • 垂直擴展有一個硬性限制,不可能向單個服務器添加無限的CPU和記憶體,
  • 垂直擴展沒有故障轉移和冗余,如果一個服務器宕機,網站/應用將完全無法訪問,

由于垂直擴展的限制,對于大規模應用程式來說,水平擴展更加理想,

在之前的設計中,用戶直接連接到Web服務器,如果Web服務器脫機,用戶將無法訪問網站,在另一種情況下,如果許多用戶同時訪問Web服務器并達到Web服務器的負載限制,用戶通常會遇到回應變慢或無法連接到服務器的問題,負載均衡器是解決這些問題的最佳技術,

負載均衡器

負載均衡器會將傳入的流量均勻分配給在負載均衡集合中定義的Web服務器,圖1-4展示了負載均衡器的作業原理,

image

如圖1-4所示,用戶直接連接負載均衡器的公共IP,通過這種設定,Web服務器不再能直接被客戶端訪問,為了更好的安全性,私有IP用于服務器之間的通信,私有IP是一個只能在同一網路中的服務器之間訪問的IP地址,無法通過互聯網訪問,負載均衡器通過私有IP與Web服務器進行通信,

在圖1-4中,當負載均衡器和第二個Web服務器添加后,我們成功解決了故障切換的問題,并提高了Web層的可用性,具體細節如下:

  • 如果服務器1下線,所有流量將被路由到服務器2,這樣可以防止網站宕機,我們還可以向服務器池中添加一個新的健康Web服務器來平衡負載,
  • 如果網站流量迅速增長,兩個服務器無法處理流量,負載均衡器可以優雅地解決這個問題,您只需要向Web服務器池添加更多服務器,負載均衡器將自動開始將請求發送給它們,

現在Web層看起來很好,那資料層呢?當前的設計只有一個資料庫,因此不支持故障轉移和冗余,資料庫復制是解決這些問題的常見技術,讓我們來看一下,

資料庫復制

參考自維基百科:“資料庫復制可以在許多資料庫管理系統中使用,通常在原始資料庫(主資料庫)和副本(從資料庫)之間建立主/從關系,” [3]

主資料庫通常僅支持寫操作,從資料庫從主資料庫獲取資料的副本,僅支持讀操作,所有的插入、洗掉或更新等修改資料的命令必須發送到主資料庫,大多數應用程式需要更高比例的讀操作與寫操作,因此系統中從資料庫的數量通常大于主資料庫的數量,圖1-5顯示了一個具有多個從資料庫的主資料庫,

image

資料庫復制的優勢:

  • 更好的性能:在主從模型中,所有的寫操作和更新操作都發生在主節點上,而讀操作分布在從節點上,這種模型改善了性能,因為它允許更多的查詢并行處理,
  • 可靠性:如果你的資料庫服務器之一被自然災害(如臺風或地震)摧毀,資料仍然得以保留,你不需要擔心資料丟失,因為資料被復制到多個位置,
  • 高可用性:通過在不同的位置復制資料,即使一個資料庫離線,你的網站仍然可以運行,因為你可以訪問存盤在另一個資料庫服務器中的資料,

在前一節中,我們討論了負載均衡器如何幫助提高系統的可用性,我們在這里提出同樣的問題:如果其中一個資料庫離線了會怎么樣?圖1-5中討論的架構設計可以處理這種情況:

  • 如果只有一個可用的從資料庫,并且它離線了,讀操作將暫時指向主資料庫,一旦問題被發現,一個新的從資料庫將取代舊的資料庫,如果有多個可用的從資料庫,讀操作將被重定向到其他健康的從資料庫,一個新的資料庫服務器將取代舊的資料庫,
  • 如果主資料庫離線了,一個從資料庫將被提升為新的主資料庫,所有的資料庫操作將在新的主資料庫上暫時執行,一個新的從資料庫將立即取代舊的資料庫進行資料復制,在生產系統中,提升新的主資料庫更為復雜,因為從資料庫中的資料可能不是最新的,需要通過運行資料恢復腳本來更新缺失的資料,雖然一些其他的復制方法,如多主和環形復制,可以提供幫助,但這些設定更加復雜,它們的討論超出了本書的范圍,有興趣的讀者可以參考所列的參考資料[4] [5],

圖1-6顯示了添加了負載均衡器和資料庫復制后的系統設計,

image

讓我們來看一下設計:

  • 用戶從DNS獲取負載均衡器的IP地址,
  • 用戶使用該IP地址連接到負載均衡器,
  • HTTP請求被路由到服務器1或服務器2,
  • Web服務器從從資料庫讀取用戶資料,
  • Web服務器將任何修改資料的操作路由到主資料庫,包括寫入、更新和洗掉操作,
  • 現在,你已經對Web和資料層有了扎實的理解,是時候通過添加快取層并將靜態內容(JavaScript/CSS/影像/視頻檔案)轉移到內容分發網路(CDN)來提高負載/回應時間了,

快取

快取是一個臨時存盤區,用于在記憶體中存盤昂貴的回應結果或經常訪問的資料,以便后續的請求可以更快地得到服務,如圖1-6所示,每次加載新的網頁時,會執行一個或多個資料庫呼叫來獲取資料,反復呼叫資料庫會嚴重影回應用程式性能,快取可以緩解這個問題,

快取層

快取層是一個比資料庫快得多的臨時資料存盤層,擁有獨立的快取層有以下好處:系統性能更好、能夠減少資料庫作業負載以及能夠獨立擴展快取層,圖1-7顯示了一個可能的快取服務器設定:

image

收到請求后,Web服務器首先檢查快取中是否有可用的回應,如果有,則將資料發送回客戶端,如果沒有,則查詢資料庫,將回應存盤在快取中,并將其發送回客戶端,這種快取策略稱為讀取穿透快取,根據資料型別、大小和訪問模式,還可以使用其他快取策略,一項以前的研究解釋了不同的快取策略如何作業[6],與快取服務器的互動非常簡單,因為大多數快取服務器為常見的編程語言提供API,以下代碼片段顯示了典型的Memcached API:

image

使用快取的注意事項

以下是使用快取系統時應考慮的幾個問題:

  • 決定何時使用快取,在資料經常被讀取但很少被修改時,考慮使用快取,由于快取資料存盤在易失性記憶體中,快取服務器不適合用于持久化資料,例如,如果快取服務器重新啟動,記憶體中的所有資料都會丟失,因此,重要的資料應保存在持久化資料存盤中,

  • 過期策略,實施過期策略是一個好的做法,一旦快取資料過期,它將從快取中洗掉,當沒有過期策略時,快取資料將永久存盤在記憶體中,建議不要將過期日期設定得太短,否則系統會過于頻繁地從資料庫重新加載資料,同時,也不建議將過期日期設定得太長,以免資料變得陳舊,

  • 一致性:這涉及保持資料存盤和快取的同步,由于資料存盤和快取上的資料修改操作不在單個事務中,所以可能發生不一致,在跨多個地區進行擴展時,保持資料存盤和快取之間的一致性是具有挑戰性的,有關詳細資訊,請參考Facebook發表的題為《Scaling Memcache at Facebook》的論文[7],

  • 減輕故障:單個快取服務器代表潛在的單點故障(SPOF),維基百科對其的定義如下:“單點故障(SPOF)是系統的一部分,如果它發生故障,將導致整個系統停止作業”[8],因此,建議在不同的資料中心中使用多個快取服務器,以避免單點故障,另一個推薦的方法是通過一定百分比進行過量配置所需的記憶體,這樣可以提供一個緩沖區,以應對記憶體使用量增加的情況,

    image

  • 淘汰策略:一旦快取已滿,任何向快取中添加項的請求都可能導致現有項被移除,這被稱為快取淘汰,最近最少使用(LRU)是最常見的快取淘汰策略,其他淘汰策略,如最不經常使用(LFU)或先進先出(FIFO),可根據不同的使用情況采用,

內容分發網路(CDN)

CDN是一個由地理分布的服務器組成的網路,用于傳送靜態內容,CDN服務器快取像影像、視頻、CSS、JavaScript檔案等靜態內容,

動態內容快取是一個相對較新的概念,超出了本書的范圍,它使得可以快取基于請求路徑、查詢字串、cookie和請求頭的HTML頁面,有關更多資訊,請參考參考資料[9]中提到的文章,本書重點介紹如何使用CDN來快取靜態內容,

以下是CDN的高級作業原理:當用戶訪問網站時,距離用戶最近的CDN服務器將傳送靜態內容,直觀來說,用戶離CDN服務器越遠,網站加載速度就越慢,例如,如果CDN服務器位于舊金山,洛杉磯的用戶將比歐洲的用戶更快地獲取內容,圖1-9是一個很好的示例,顯示了CDN如何提高加載時間,

image

圖1-10展示了CDN的作業流程,

image

  1. 用戶A嘗試使用影像URL獲取image.png,URL的域名由CDN提供商提供,以下兩個影像URL是用來演示Amazon和Akamai CDN上影像URL的樣例:
    • https://mysite.cloudfront.net/logo.jpg
    • https://mysite.akamai.com/image-manager/img/logo.jpg
  2. 如果CDN服務器沒有image.png的快取,CDN服務器會從源(可以是Web服務器或像Amazon S3這樣的在線存盤)請求檔案,
  3. 源將image.png回傳給CDN服務器,其中包括可選的HTTP頭部Time-to-Live(TTL),描述影像被快取的時間,
  4. CDN快取影像并將其回傳給用戶A,影像會在CDN中快取,直到TTL過期,
  5. 用戶B發送請求以獲取相同的影像,
  6. 只要TTL未過期,影像將從快取中回傳,

CDN 使用的考慮因素

  • 成本:CDN 由第三方提供商運營,您需要支付 CDN 內外的資料傳輸費用,對于不經常使用的資源,快取并沒有顯著的好處,所以您應該考慮將其移出 CDN,
  • 設定適當的快取過期時間:對于時間敏感的內容,設定快取過期時間非常重要,快取過期時間既不能太長也不能太短,如果時間太長,內容可能已經不新鮮,如果時間太短,可能會導致重復從源服務器重新加載內容到 CDN,
  • CDN 回退:您應該考慮您的網站/應用程式如何應對 CDN 故障,如果出現臨時的 CDN 中斷,客戶端應該能夠檢測到問題并從源獲取資源,
  • 使檔案失效:您可以在檔案過期之前從 CDN 中移除檔案,具體操作有以下幾種:
    • 使用 CDN 供應商提供的 API 使 CDN 物件失效,
    • 使用物件版本控制來提供不同版本的物件,要對物件進行版本控制,可以向 URL 添加引數,比如版本號,例如,查詢字串中添加版本號 2:image.png?v=2,

圖 1-11 展示了在添加 CDN 和快取后的設計,

image

  1. 靜態資源(JS、CSS、圖片等)不再由 Web 服務器提供,它們從 CDN 獲取以獲得更好的性能,
  2. 通過快取資料減輕了資料庫的負載,

無狀態的Web層

現在是考慮水平擴展Web層的時候了,為此,我們需要將狀態(例如用戶會話資料)從Web層中移出,一個很好的做法是將會話資料存盤在持久性存盤中,如關系型資料庫或NoSQL資料庫,集群中的每個Web服務器都可以從資料庫中訪問狀態資料,這被稱為無狀態的Web層,

有狀態架構

有狀態服務器和無狀態服務器有一些關鍵區別,有狀態服務器會記住從一個請求到下一個請求的客戶端資料(狀態),無狀態服務器不保存任何狀態資訊,

圖1-12顯示了一個有狀態架構的示例,

image

在圖1-12中,用戶A的會話資料和個人資料圖片存盤在服務器1中,要對用戶A進行身份驗證,HTTP請求必須路由到服務器1,如果請求被發送到其他服務器,如服務器2,身份驗證將失敗,因為服務器2不包含用戶A的會話資料,同樣,來自用戶B的所有HTTP請求必須路由到服務器2;來自用戶C的所有請求必須發送到服務器3,

問題在于同一客戶端的每個請求必須路由到同一臺服務器,在大多數負載均衡器中,可以通過粘性會話來實作這一點[10];然而,這會增加開銷,使用這種方法更加困難地添加或洗掉服務器,處理服務器故障也是一項挑戰,

無狀態架構

圖1-13展示了無狀態架構,

image

在這種無狀態架構中,用戶的HTTP請求可以發送到任何Web服務器,這些服務器從共享資料存盤中獲取狀態資料,狀態資料存盤在共享資料存盤中,并且不保存在Web服務器中,無狀態系統更簡單、更健壯和可擴展,

圖1-14展示了帶有無狀態Web層的更新設計,

image

在圖1-14中,我們將會話資料從Web層移出,并將其存盤在持久資料存盤中,共享資料存盤可以是關系資料庫、Memcached/Redis、NoSQL等,選擇NoSQL資料存盤是因為它易于擴展,自動擴展意味著根據流量負載自動添加或洗掉Web服務器,在狀態資料從Web服務器中移除后,根據流量負載添加或洗掉服務器輕松實作Web層的自動擴展,

您的網站快速增長,并吸引了大量國際用戶,為了提高可用性并在更廣泛的地理區域提供更好的用戶體驗,支持多個資料中心至關重要,

資料中心

圖1-15顯示了一個擁有兩個資料中心的示例設定,在正常運行時,用戶會根據地理位置通過geoDNS路由到最近的資料中心,其中在美國東部的流量占x%,在美國西部的流量占(100 - x)%,geoDNS是一種DNS服務,根據用戶所在地將域名決議為IP地址,

image

如果發生任何重大資料中心故障,我們會將所有流量引導到一個正常運行的資料中心,在圖1-16中,資料中心2(美國西部)離線,100%的流量被路由到資料中心1(美國東部),

image

要實作多資料中心設定,需要解決一些技術挑戰:

  • 流量重定向:需要有效的工具將流量引導到正確的資料中心,根據用戶所在地,可以使用geoDNS將流量引導到最近的資料中心,
  • 資料同步:來自不同地區的用戶可能使用不同的本地資料庫或快取,在故障轉移情況下,流量可能會路由到一個資料中心,該資料中心的資料不可用,一種常見的策略是在多個資料中心之間復制資料,一項先前的研究展示了Netflix如何實作異步多數據中心復制[11],
  • 測驗和部署:對于多資料中心設定,重要的是在不同的位置測驗您的網站/應用程式,自動化部署工具對于保持所有資料中心的服務一致至關重要[11],

為了進一步擴展我們的系統,我們需要解耦系統的不同組件,使它們可以獨立擴展,訊息佇列是許多實際分布式系統用于解決這個問題的關鍵策略,

訊息佇列

訊息佇列是一種持久性組件,存盤在記憶體中,用于支持異步通信,它作為緩沖區并分發異步請求,訊息佇列的基本架構很簡單,稱為生產者/發布者的輸入服務創建訊息,并將其發布到訊息佇列中,其他服務或服務器,稱為消費者/訂閱者,連接到佇列并執行訊息定義的操作,模型如圖1-17所示,

image

解耦使訊息佇列成為構建可擴展和可靠應用程式的首選架構,使用訊息佇列,當消費者無法處理訊息時,生產者可以將訊息發布到佇列中,即使生產者不可用,消費者也可以從佇列中讀取訊息,

考慮以下用例:您的應用程式支持照片定制,包括裁剪、銳化、模糊等操作,這些定制任務需要時間來完成,在圖1-18中,Web服務器將照片處理作業發布到訊息佇列中,照片處理作業者從訊息佇列中接收作業,并異步執行照片定制任務,生產者和消費者可以獨立擴展,當佇列的大小變大時,可以添加更多作業者以減少處理時間,然而,如果佇列大部分時間為空,作業者的數量可以減少,

image

日志記錄、指標、自動化

在處理只運行在幾臺服務器上的小型網站時,日志記錄、指標和自動化支持是良好的實踐,但并非必需,然而,現在你的網站已經發展成為一個為大型企業提供服務的網站,投資于這些工具是必不可少的,

日志記錄:監控錯誤日志非常重要,因為它有助于識別系統中的錯誤和問題,您可以在每個服務器級別監控錯誤日志,也可以使用工具將它們聚合到一個集中式服務中,以便進行簡單的搜索和查看,

指標:收集不同型別的指標有助于我們獲取業務見解并了解系統的健康狀況,以下是一些有用的指標:

  • 主機級別的指標:CPU、記憶體、磁盤I/O等,
  • 聚合級別的指標:例如整個資料庫層、快取層等的性能,
  • 關鍵業務指標:每榷訓躍用戶、留存率、收入等,

自動化:當系統變得龐大而復雜時,我們需要構建或利用自動化工具來提高生產效率,持續集成是一種良好的實踐,通過自動化驗證每次代碼提交,使團隊能夠早期發現問題,此外,自動化構建、測驗、部署流程等可以顯著提高開發人員的生產力,

添加訊息佇列和其他工具

圖1-19顯示了更新后的設計,由于空間限制,圖中只顯示了一個資料中心,

  1. 設計中包括一個訊息佇列,有助于使系統更松散耦合和具有容錯性,
  2. 包括了日志記錄、監控、指標和自動化工具,

image

隨著每天資料的增長,您的資料庫負荷越來越重,是時候對資料層進行擴展了,

資料庫擴展

資料庫擴展有兩種主要方法:垂直擴展和水平擴展,

垂直擴展

也稱為縱向擴展,是通過向現有機器添加更多的性能(CPU、RAM、DISK等)來進行擴展,有一些功能強大的資料庫服務器,根據亞馬遜關系資料庫服務(RDS)[12],你可以獲得一臺具有24 TB RAM的資料庫服務器,這種強大的資料庫服務器可以存盤和處理大量的資料,例如,2013年的stackoverflow.com每月有超過1000萬的獨立訪問者,但它只有1個主資料庫[13],然而,垂直擴展也存在一些嚴重的缺點:

  • 你可以為資料庫服務器添加更多的CPU、RAM等,但存在硬體限制,如果你有大量的用戶,單個服務器是不夠的,
  • 單點故障的風險增加,
  • 垂直擴展的總體成本較高,強大的服務器更加昂貴,

水平擴展

也稱為分片,是添加更多服務器的做法,圖1-20比較了垂直擴展和水平擴展,

image

分片將大型資料庫分割成更小、更易管理的部分,稱為分片,每個分片共享相同的模式,盡管每個分片上的實際資料是唯一的,

圖1-21展示了分片資料庫的示例,用戶資料根據用戶ID分配到資料庫服務器上,每當你訪問資料時,都會使用散列函式來找到相應的分片,在我們的示例中,user_id % 4被用作散列函式,如果結果等于0,則使用分片0來存盤和獲取資料,如果結果等于1,則使用分片1,其他分片的邏輯也是相同的,

image

圖1-22展示了分片資料庫中的用戶表,

image

在實施分片策略時,最重要的因素是選擇分片鍵,分片鍵(也稱為磁區鍵)由一個或多個列組成,用于確定資料的分布方式,如圖1-22所示,“user_id”是分片鍵,分片鍵允許你通過將資料庫查詢路由到正確的資料庫來高效地檢索和修改資料,在選擇分片鍵時,最重要的一個標準是選擇一個能夠均勻分布資料的鍵,

分片是擴展資料庫的一種很好的技術,但遠非完美的解決方案,它給系統引入了復雜性和新的挑戰:

重新分片資料:當1)單個分片由于快速增長而無法再容納更多資料時,需要重新分片資料,2)某些分片可能由于不均勻的資料分布而更快地耗盡分片,當分片耗盡時,需要更新分片函式并移動資料,一種常用的解決此問題的技術是一致性哈希,將在第5章中討論,

熱點鍵問題:也稱為明星問題,對特定分片的過度訪問可能導致服務器超載,想象一下,Katy Perry、Justin Bieber和Lady Gaga的資料都最終存盤在同一個分片上,對于社交應用來說,該分片將被讀操作淹沒,為了解決這個問題,我們可能需要為每個名人分配一個分片,甚至每個分片可能還需要進一步磁區,

連接和去規范化:一旦資料庫被分片到多個服務器上,執行跨資料庫分片的連接操作就變得困難,一個常見的解決方法是對資料庫進行去規范化,以便可以在單個表中執行查詢,

在圖1-23中,我們對資料庫進行分片以支持快速增長的資料流量,與此同時,一些非關系型功能被移到NoSQL資料存盤中,以減輕資料庫負載,這是一篇涵蓋了NoSQL許多使用案例的文章[14],

image

超過數百萬用戶的規模

系統的擴展是一個迭代的程序,根據本章學到的知識進行迭代可能會使我們走得更遠,為了超越數百萬用戶,需要更多的優化和新策略,例如,您可能需要優化您的系統并將系統解耦為更小的服務,本章學到的所有技術應該為應對新的挑戰提供了良好的基礎,為了總結本章,我們提供了如何擴展我們的系統以支持數百萬用戶的摘要:

  • 保持 Web 層無狀態
  • 在每個層面上構建冗余性
  • 盡可能地快取資料
  • 支持多個資料中心
  • 在 CDN 中托管靜態資源
  • 通過分片擴展資料層
  • 將層級拆分為獨立的服務
  • 監控您的系統并使用自動化工具

恭喜您取得了如此大的進展!現在給自己一個鼓勵,做得好!

AI不會取代你,使用AI的人會,歡迎關注我的公眾號:更AI,以程式員的視角來看AI能帶給我們什么~

參考資料

[1] 超文本傳輸協議(Hypertext Transfer Protocol): https://zh.wikipedia.org/wiki/超文本傳輸協議

[2] 你是否應該超越關系型資料庫?:

https://blog.teamtreehouse.com/should-you-go-beyond-relational-databases

[3] 復制(Replication): https://zh.wikipedia.org/wiki/復制_(計算機)

[4] 多主復制(Multi-master replication):

https://zh.wikipedia.org/wiki/多主復制

[5] NDB 集群復制:多主和環形復制:

https://dev.mysql.com/doc/refman/5.7/en/mysql-cluster-replication-multi-master.html

[6] 快取策略及如何選擇合適的策略:

https://codeahoy.com/2017/08/11/caching-strategies-and-how-to-choose-the-right-one/

[7] R. Nishtala,“Facebook 的快取擴展”,第十屆 USENIX 網路系統設計與實作研討會(NSDI '13),

[8] 單點故障(Single point of failure): https://zh.wikipedia.org/wiki/單點故障

[9] Amazon CloudFront 動態內容傳送:

https://aws.amazon.com/cloudfront/dynamic-content/

[10] 配置經典負載均衡器的黏性會話:

https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-sticky-sessions.html

[11] 多區域容錯性的主動-主動(Active-Active):

https://netflixtechblog.com/active-active-for-multi-regional-resiliency-c47719f6685b

[12] Amazon EC2 高記憶體實體:

https://aws.amazon.com/ec2/instance-types/high-memory/

[13] 運行 Stack Overflow 的所需條件:

http://nickcraver.com/blog/2013/11/22/what-it-takes-to-run-stack-overflow

[14] 你到底在使用 NoSQL 做什么:

http://highscalability.com/blog/2010/12/6/what-the-heck-are-you-actually-using-nosql-for.html

本文翻譯自《System Design Interview: An Insider’s Guide》第一章,如有侵權,請聯系本人洗掉

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/553669.html

標籤:架構設計

上一篇:基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《原型篇一》[已開源]

下一篇:返回列表

標籤雲
其他(159895) Python(38178) JavaScript(25460) Java(18141) C(15232) 區塊鏈(8268) C#(7972) AI(7469) 爪哇(7425) MySQL(7214) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5343) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4577) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1977) 功能(1967) Web開發(1951) HtmlCss(1949) C++(1924) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1878) .NETCore(1862) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 系統設計:從零用戶擴展到百萬用戶

    設計一個支持百萬用戶的系統是具有挑戰性的,這是一段需要不斷改進和不斷提升的旅程。在本章中,我們將構建一個支持單個用戶的系統,并逐漸擴展以服務于數百萬用戶。閱讀本章后,您將掌握一些技巧,幫助您解決系統設計面試問題。 > AI不會取代你,使用AI的人會。歡迎關注我的公眾號:更AI。以程式員的視角來看AI ......

    uj5u.com 2023-05-29 09:02:21 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    還在一行一行地手擼查詢代碼嗎?有沒有想過全自動的,通用的,免寫代碼的動態查詢?上一篇簡略講了如何根據前面設計的查詢描述器構造出可執行的運算式的原理,本篇來講講如何用C#代碼實作俄羅斯套娃般的多層嵌套查詢Expression Lambda運算式的動態自動構建。 ......

    uj5u.com 2023-05-28 08:29:44 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    還在一行一行地手擼查詢代碼嗎?有沒有想過全自動的,通用的,免寫代碼的動態查詢?上一篇簡略講了如何根據前面設計的查詢描述器構造出可執行的運算式的原理,本篇來講講如何用C#代碼實作俄羅斯套娃般的多層嵌套查詢Expression Lambda運算式的動態自動構建。 ......

    uj5u.com 2023-05-28 08:29:16 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    還在手擼查詢代碼嗎?有沒有想過全自動的,通用的,免寫代碼的動態查詢?上一篇簡略講了如何把查詢條件用代碼描述出來,本篇接繼來講講,如何根據前面設計好查詢描述器構造出可執行的運算式。 ......

    uj5u.com 2023-05-27 07:48:27 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    還在手擼查詢代碼嗎?有沒有想過全自動的,通用的,免寫代碼的動態查詢?上一篇簡略講了如何把查詢條件用代碼描述出來,本篇接繼來講講,如何根據前面設計好查詢描述器構造出可執行的運算式。 ......

    uj5u.com 2023-05-27 07:47:57 more
  • 什么是一致性哈希?一致性哈希是如何作業的?如何設計一致性哈希?

    如果你有 *n* 個快取服務器,一個常見的負載均衡方式是使用以下的哈希方法: *服務器索引 = 哈希(鍵) % N*,其中 *N* 是服務器池的大小。 讓我們通過一個例子來說明這是如何作業的。如表5-1所示,我們有4臺服務器和8個字串鍵及其哈希值。 ![image-2023052022160981 ......

    uj5u.com 2023-05-26 13:45:31 more
  • 什么是一致性哈希?一致性哈希是如何作業的?如何設計一致性哈希?

    如果你有 *n* 個快取服務器,一個常見的負載均衡方式是使用以下的哈希方法: *服務器索引 = 哈希(鍵) % N*,其中 *N* 是服務器池的大小。 讓我們通過一個例子來說明這是如何作業的。如表5-1所示,我們有4臺服務器和8個字串鍵及其哈希值。 ![image-2023052022160981 ......

    uj5u.com 2023-05-26 13:30:11 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    基于Expression Lambda運算式樹的通用復雜動態查詢構建器。在上一篇中構思了把查詢子句描述出來的資料結構,那么能否用代碼將其表達出來,如何表達呢?本篇來講講查詢描述器的構思。 ......

    uj5u.com 2023-05-25 09:21:31 more
  • 微服務架構基本原理學習筆記(一)

    一、什么是微服務 微服務是一種技術架構,通常我們可以把它理解為一組可以相互之間協同作業的應用程式或服務,這些應用程式或服務能夠被單獨部署到不同的服務器中,并且能夠自主運行和維護。 微服務技術只是一個名稱而已,或許我們在日常作業中已經或多或少在使用其中的一種或幾種技術和架構,但我們并沒有將其稱之為微服 ......

    uj5u.com 2023-05-25 09:21:12 more
  • 基于Expression Lambda運算式樹的通用復雜動態查詢構建器——《

    基于Expression Lambda運算式樹的通用復雜動態查詢構建器。在上一篇中構思了把查詢子句描述出來的資料結構,那么能否用代碼將其表達出來,如何表達呢?本篇來講講查詢描述器的構思。 ......

    uj5u.com 2023-05-25 09:20:40 more