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

来源:https://www.cnblogs.com/powerai/archive/2023/05/28/17438523.html
-Advertisement-
Play Games

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


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

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的樣例:
  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》第一章,如有侵權,請聯繫本人刪除


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • **一、什麼是PID** 學過自動控制原理的對PID並不陌生,PID控制是對偏差信號e(t)進行比例、積分和微分運算變換後形成的一種控制規律。PID 演算法的一般形式: ![](https://img2023.cnblogs.com/blog/2776504/202305/2776504-202305 ...
  • # 協程 > 線程分為用戶級線程,內核級線程和輕量級線程。Linux中使用的是輕量級線程,而協程雖然是運行線上程之上,但是是run在用戶空間。並且協程和線程一樣,擁有自己的調度器、cpu的上下文切換等。 > > 協程在我個人看來是一種用戶級線程; > > - 這是因為對於cpu有上下文的切換,而且是 ...
  • # 痞子衡嵌入式半月刊: 第 77 期 ![](http://henjay724.com/image/cnblogs/pzh_mcu_bi_weekly.PNG) 這裡分享嵌入式領域有用有趣的項目/工具以及一些熱點新聞,農曆年分二十四節氣,希望在每個交節之日準時發佈一期。 本期刊是開源項目(GitH ...
  • Ethernet over EtherCAT (EoE) 是一種通信協議,它允許通過網路連接訪問從站設備的參數,以便配置和診斷從站設備。EoE 允許將常見的互聯網協議(如 HTTP、FTP 等)的數據插入到 EtherCAT 協議數據中,而不影響 EtherCAT 過程數據 ,那ETherCAT主站... ...
  • ## 查看死鎖 ```sql SELECT s.sid "會話ID", s.lockwait "等待鎖", s.event "等待的資源/事件", -- 最近等待或正在等待的資源/事件 DECODE(lo.locked_mode, 0, '尚未獲得鎖', 1, NULL, 2, '行共用鎖', 3, ...
  • # 索引 索引用於幫助快速過濾或查找數據。 目前 Doris 主要支持兩類索引: • 內建的智能索引:包括首碼索引和 ZoneMap 索引。 • 用戶創建的二級索引:包括 Bloom Filter 索引 和 Bitmap倒排索引。 其中 ZoneMap 索引是在列存格式上,對每一列自動維護的索引信息 ...
  • # HTML實用合集1 ## 1.框架 使用英文!,按tab鍵出現框架。 ![uTools_1685239763398](https://img2023.cnblogs.com/blog/3178390/202305/3178390-20230528120408799-1395303523.png) ...
  • WMS產品實時數據倉庫介紹 目標以ERP、跨境電商ERP 、 WMS(倉儲管理系統)為核心,搭建融合商業智能BI、新零售、訂貨系統等為一體的產品矩陣,幫助電商企業快速佈局 跨境 和 新零售,提升訂單處理效率,實現數字化業務管理,為企業降本增效。痛點業務+數據雙中台 Hologres是阿裡巴巴自主研發 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...