English ∙ 日本文 ∙ 簡體中文 ∙ 繁體中文 | ∙ বাংলা ∙ 巴西葡萄牙語 ∙ 德語 ∙ ελληνικά ∙ עברйת ∙ 義大利文ык ∙ 西班牙語 ∙ ภาษาไทย ∙ 土耳其語 ∙ tiếng 越南語 ∙ 法語 |新增翻譯
幫忙翻譯一下這個指南!
了解如何設計大型系統。
準備系統設計面試。
學習如何設計可擴展的系統將幫助您成為更好的工程師。
系統設計是一個廣泛的議題。網路上分佈著大量有關係統設計原理的資源。
此儲存庫是一個有組織的資源集合,可幫助您學習如何大規模建置系統。
這是一個不斷更新的開源專案。
歡迎貢獻!
除了程式設計面試之外,系統設計也是許多科技公司技術面試過程中必需的組成部分。
練習常見的系統設計面試問題,並將您的結果與範例解決方案進行比較:討論、程式碼和圖表。
面試準備的其他主題:
提供的 Anki 抽認卡組使用間隔重複來幫助您保留關鍵的系統設計概念。
非常適合在旅途中使用。
正在尋找資源來幫助您準備程式設計面試?
查看姐妹存儲庫Interactive Coding Challenges ,其中包含額外的 Anki 套牌:
向社區學習。
請隨時提交拉取請求來幫助:
需要一些潤飾的內容正在開發中。
查看貢獻指南。
各種系統設計主題的總結,包括優點和缺點。一切都是一個權衡。
每個部分都包含指向更深入資源的連結。
根據您的面試時間軸(短、中、長)建議複習的主題。
Q:對於面試,我需要知道這裡的一切嗎?
A:不,你不需要知道這裡的一切來準備面試。
您在面試中被問到的問題取決於以下變數:
經驗豐富的候選人通常應該了解更多關於係統設計的知識。架構師或團隊領導可能需要比個人貢獻者了解更多。頂尖科技公司可能會進行一輪或多輪設計面試。
從廣泛的領域入手,然後在幾個領域進行深入研究。了解一些關鍵的系統設計主題會有所幫助。根據您的時間表、經驗、您要面試的職位以及您要面試的公司來調整以下指南。
短的 | 中等的 | 長的 | |
---|---|---|---|
通讀系統設計主題,廣泛了解系統的工作原理 | ? | ? | ? |
閱讀您正在面試的公司的公司工程部落格中的幾篇文章 | ? | ? | ? |
通讀一些現實世界的架構 | ? | ? | ? |
回顧如何處理系統設計面試問題 | ? | ? | ? |
解決系統設計面試問題及其解決方案 | 一些 | 許多 | 最多 |
解決物件導向設計面試問題及其解決方案 | 一些 | 許多 | 最多 |
查看其他系統設計面試問題 | 一些 | 許多 | 最多 |
如何解決系統設計面試問題。
系統設計面試是一個開放式的對話。您應該領導它。
您可以使用以下步驟來指導討論。為了幫助鞏固此流程,請使用以下步驟完成系統設計面試問題和解決方案部分。
收集需求並確定問題範圍。提出問題以澄清用例和限制。討論假設。
概述包含所有重要組件的高級設計。
深入了解每個核心組件的詳細資訊。例如,如果您被要求設計一個 url 縮短服務,請討論:
考慮到限制,識別並解決瓶頸。例如,您是否需要以下內容來解決可擴充性問題?
討論潛在的解決方案和權衡。一切都是一個權衡。使用可擴展系統設計原則解決瓶頸。
您可能會被要求手動進行一些估計。請參閱附錄以取得以下資源:
查看以下連結以更好地了解預期內容:
常見的系統設計面試問題,包含範例討論、程式碼和圖表。
連結到
solutions/
資料夾中內容的解決方案。
問題 | |
---|---|
設計 Pastebin.com(或 Bit.ly) | 解決方案 |
設計 Twitter 時間軸和搜尋(或 Facebook 動態和搜尋) | 解決方案 |
設計一個網路爬蟲 | 解決方案 |
設計 Mint.com | 解決方案 |
設計社交網路的資料結構 | 解決方案 |
為搜尋引擎設計鍵值存儲 | 解決方案 |
按類別特色設計亞馬遜銷售排名 | 解決方案 |
設計一個可在 AWS 上擴展到數百萬用戶的系統 | 解決方案 |
新增系統設計問題 | 貢獻 |
查看練習和解決方案
查看練習和解決方案
查看練習和解決方案
查看練習和解決方案
查看練習和解決方案
查看練習和解決方案
查看練習和解決方案
查看練習和解決方案
常見的物件導向設計面試問題,包含範例討論、程式碼和圖表。
連結到
solutions/
資料夾中內容的解決方案。
注意:此部分正在開發中
問題 | |
---|---|
設計一個哈希圖 | 解決方案 |
設計最近最少使用的緩存 | 解決方案 |
設計一個呼叫中心 | 解決方案 |
設計一副紙牌 | 解決方案 |
設計一個停車場 | 解決方案 |
設計一個聊天伺服器 | 解決方案 |
設計一個圓形陣列 | 貢獻 |
新增物件導向的設計問題 | 貢獻 |
系統設計新手?
首先,您需要對常見原則有基本的了解,以了解它們是什麼、如何使用以及它們的優點和缺點。
哈佛大學可擴展性講座
可擴展性
接下來,我們將看看高層的權衡:
請記住,一切都是一個權衡。
接著我們將深入探討更具體的主題,例如 DNS、CDN 和負載平衡器。
如果服務以與添加的資源成比例的方式提高效能,則該服務是可擴展的。一般來說,提高效能意味著服務更多的工作單元,但也可以處理更大的工作單元,例如當資料集成長時。 1
另一種看待效能與可擴充性的方法:
延遲是執行某些操作或產生某些結果的時間。
吞吐量是每單位時間此類操作或結果的數量。
一般來說,您應該以可接受的延遲為目標實現最大吞吐量。
資料來源:CAP 定理重溫
在分散式電腦系統中,只能支援以下保證中的兩個:
網路並不可靠,因此您需要支援分區容錯。您需要在軟體一致性和可用性之間進行權衡。
等待分區節點的回應可能會導致逾時錯誤。如果您的業務需要原子讀寫,CP 是一個不錯的選擇。
回應傳回任何節點上可用資料的最容易取得的版本,該版本可能不是最新的。解析分區後,寫入可能需要一些時間才能傳播。
如果業務需要實現最終一致性,或者係統需要在外部錯誤的情況下繼續工作,那麼 AP 是一個不錯的選擇。
對於相同資料的多個副本,我們面臨著如何同步它們的選擇,以便客戶端擁有一致的資料視圖。回想一下 CAP 定理中一致性的定義 - 每次讀取都會收到最近的寫入或錯誤。
寫入後,讀取可能會也可能看不到它。採取盡力而為的方法。
這種方法常見於 memcached 等系統。弱一致性在 VoIP、視訊聊天和即時多人遊戲等即時用例中效果很好。例如,如果您正在打電話,但訊號中斷了幾秒鐘,那麼當您重新獲得連線時,您將聽不到連線中斷期間所說的內容。
寫入後,讀取最終會看到它(通常在幾毫秒內)。資料是異步複製的。
這種方法常見於 DNS 和電子郵件等系統。最終一致性在高可用系統中效果很好。
寫入後,讀取會看到它。資料同步複製。
這種方法常見於檔案系統和 RDBMS 中。強一致性在需要事務的系統中效果很好。
有兩種互補的模式可以支援高可用性:故障轉移和複製。
透過主動-被動故障轉移,心跳在主動和備用伺服器之間發送。如果心跳中斷,被動伺服器將接管主動伺服器的 IP 位址並恢復服務。
停機時間的長短取決於被動伺服器是否已經在「熱」備用狀態下運行,或者是否需要從「冷」備用狀態啟動。只有活動伺服器處理流量。
主動-被動故障轉移也可以稱為主從故障轉移。
在主動-主動模式下,兩台伺服器都在管理流量,在它們之間分散負載。
如果伺服器面向公眾,則 DNS 需要了解兩台伺服器的公共 IP。如果伺服器面向內部,應用程式邏輯將需要了解這兩個伺服器。
主動-主動故障轉移也可以稱為主-主故障轉移。
該主題將在資料庫部分進一步討論:
可用性通常透過正常運作時間(或停機時間)來量化,作為服務可用時間的百分比。可用性通常以 9 的數量來衡量——可用性為 99.99% 的服務被描述為有四個 9。
期間 | 可接受的停機時間 |
---|---|
每年停機時間 | 8小時45分57秒 |
每月停機時間 | 43m 49.7s |
每週停機時間 | 10m 4.8s |
每天的停機時間 | 1m 26.4s |
期間 | 可接受的停機時間 |
---|---|
每年停機時間 | 52分35.7秒 |
每月停機時間 | 4米23秒 |
每週停機時間 | 1米5秒 |
每天的停機時間 | 8.6秒 |
如果一項服務由多個容易發生故障的元件組成,則該服務的整體可用性取決於這些元件是順序排列還是並行排列。
當可用性 < 100% 的兩個元件依序排列時,整體可用性會降低:
Availability (Total) = Availability (Foo) * Availability (Bar)
如果Foo
和Bar
可用性均為 99.9%,則它們的總可用性依序為 99.8%。
當可用性 < 100% 的兩個元件並行時,整體可用性會提高:
Availability (Total) = 1 - (1 - Availability (Foo)) * (1 - Availability (Bar))
如果Foo
和Bar
都具有 99.9% 的可用性,那麼它們並行的總可用性將為 99.9999%。
來源:DNS 安全演示
網域名稱系統 (DNS) 將網域名稱(例如 www.example.com)轉換為 IP 位址。
DNS 是分層的,頂層有一些權威伺服器。您的路由器或 ISP 提供有關在進行查找時要聯絡哪些 DNS 伺服器的資訊。較低層級的 DNS 伺服器快取映射,這些映射可能會因 DNS 傳播延遲而變得過時。 DNS 結果也可以由您的瀏覽器或作業系統快取一段時間,具體時間由生存時間 (TTL) 決定。
CNAME
(example.com 到 www.example.com)或A
記錄。CloudFlare 和 Route 53 等服務提供託管 DNS 服務。有些 DNS 服務可以透過各種方法路由流量:
來源:為什麼要使用 CDN
內容分發網絡 (CDN) 是一個全球分散式代理伺服器網絡,從更靠近使用者的位置提供內容。通常,靜態檔案(例如 HTML/CSS/JS、照片和影片)由 CDN 提供,但某些 CDN(例如 Amazon 的 CloudFront)支援動態內容。該網站的 DNS 解析將告訴客戶端要聯絡哪個伺服器。
從 CDN 提供內容可以透過兩種方式顯著提高效能:
每當您的伺服器發生變更時,推送 CDN 都會收到新內容。您對提供內容、直接上傳到 CDN 以及重寫 URL 以指向 CDN 承擔全部責任。您可以配置內容何時過期以及何時更新。僅當內容是新的或更改時才上傳,從而最大限度地減少流量,但最大限度地提高儲存空間。
流量較小的網站或內容不經常更新的網站可以很好地使用推送 CDN。內容一次放置在 CDN 上,而不是定期重新拉取。
當第一個使用者請求內容時,拉取 CDN 從您的伺服器取得新內容。您將內容保留在伺服器上並重寫 URL 以指向 CDN。這會導致請求速度變慢,直到內容快取在 CDN 上。
生存時間 (TTL) 決定內容的快取時間。拉取 CDN 最大限度地減少了 CDN 上的儲存空間,但如果檔案過期並在實際變更之前被拉取,則可能會產生冗餘流量。
流量大的網站可以很好地使用拉式 CDN,因為流量分佈得更均勻,CDN 上僅保留最近請求的內容。
來源:可擴展系統設計模式
負載平衡器將傳入的客戶端請求分發到應用程式伺服器和資料庫等運算資源。在每種情況下,負載平衡器都會將回應從運算資源傳回適當的客戶端。負載平衡器可以有效:
負載平衡器可以使用硬體(昂貴)或使用 HAProxy 等軟體來實現。
其他好處包括:
為了防止故障,通常會以主動-被動或主動-主動模式設定多個負載平衡器。
負載平衡器可以根據各種指標路由流量,包括:
第 4 層負載平衡器查看傳輸層的資訊來決定如何分發請求。通常,這涉及標頭中的來源、目標 IP 位址和端口,但不涉及封包的內容。第 4 層負載平衡器將網路封包轉送到上游伺服器或從上游伺服器轉送網路封包,執行網路位址轉換 (NAT)。
第 7 層負載平衡器檢視應用程式層來決定如何分發請求。這可能涉及標頭、訊息和 cookie 的內容。第 7 層負載平衡器終止網路流量,讀取訊息,做出負載平衡決策,然後開啟與所選伺服器的連線。例如,第 7 層負載平衡器可以將視訊流量導向到託管影片的伺服器,同時將更敏感的使用者計費流量導向到安全強化的伺服器。
以靈活性為代價,第 4 層負載平衡所需的時間和運算資源比第 7 層更少,儘管對現代商用硬體的效能影響可能很小。
負載平衡器還可以幫助水平擴展,提高效能和可用性。與在更昂貴的硬體上擴展單一伺服器相比,使用商用機器進行擴充更具成本效益,並且可帶來更高的可用性,稱為垂直擴展。與專門的企業系統相比,僱用從事商品硬體工作的人才也更容易。
資料來源:維基百科
反向代理是一種集中內部服務並向公眾提供統一介面的Web伺服器。在反向代理將伺服器的回應傳回給客戶端之前,來自客戶端的請求將轉送到可以滿足請求的伺服器。
其他好處包括:
來源:規模化系統架構簡介
將 Web 層與應用程式層(也稱為平台層)分開可讓您獨立擴展和配置這兩個層。新增的 API 會導致新增應用程式伺服器,而無需新增額外的 Web 伺服器。單一責任原則提倡小型且自主的服務協同工作。擁有小型服務的小型團隊可以更積極地規劃以實現快速成長。
應用程式層的工作人員也有助於實現非同步。
與此討論相關的是微服務,它可以被描述為一套可獨立部署的小型模組化服務。每個服務都運行一個獨特的流程,並透過定義明確的輕量級機制進行通信,以服務業務目標。 1
例如,Pinterest 可以有以下微服務:使用者個人資料、追蹤者、提要、搜尋、照片上傳等。
Consul、Etcd 和 Zookeeper 等系統可以透過追蹤註冊名稱、位址和連接埠來幫助服務找到彼此。執行狀況檢查有助於驗證服務完整性,通常使用 HTTP 端點完成。 Consul 和 Etcd 都有一個內建的鍵值存儲,可用於存儲配置值和其他共享資料。
資料來源:擴展到前 1,000 萬用戶
像 SQL 這樣的關聯式資料庫是按表組織的資料項的集合。
ACID是關係型資料庫事務的一組屬性。
有許多技術可以擴展關聯式資料庫:主從複製、主主複製、聯合、分片、非規範化和SQL 調優。
主伺服器提供讀取和寫入服務,將寫入複製到一個或多個僅提供讀取服務的從伺服器。從屬設備也可以以樹狀方式複製到其他從屬設備。如果主設備離線,系統可以繼續以唯讀模式運行,直到從設備升級為主設備或配置新的主設備。
來源:可擴展性、可用性、穩定性、模式
兩個主機都提供讀取和寫入服務,並在寫入時相互協調。如果任一主設備故障,系統可以繼續進行讀寫操作。
來源:可擴展性、可用性、穩定性、模式
資料來源:擴展到前 1,000 萬用戶
聯合(或功能分區)依功能分割資料庫。例如,您可以擁有三個資料庫,而不是單一整體資料庫: forums 、 users和products ,從而減少每個資料庫的讀寫流量,從而減少複製延遲。較小的資料庫會導致記憶體中可以容納的資料更多,進而由於快取局部性的改進而導致更多的快取命中。由於沒有單一中央主控串列寫入,您可以並行寫入,從而提高吞吐量。
來源:可擴展性、可用性、穩定性、模式
分片將資料分佈在不同的資料庫中,使得每個資料庫只能管理資料的子集。以使用者資料庫為例,隨著使用者數量的增加,叢集中會增加更多的分片。
與聯合的優點類似,分片會導致更少的讀寫流量、更少的複製和更多的快取命中。索引大小也減少了,這通常可以透過更快的查詢來提高效能。如果一個分片出現故障,其他分片仍然可以運行,儘管您需要添加某種形式的複製以避免資料遺失。與聯合一樣,沒有單一中央主控器序列化寫入,因此您可以並行寫入並提高吞吐量。
對使用者表進行分片的常見方法是透過使用者的姓氏首字母或使用者的地理位置。
非規範化試圖以犧牲部分寫入效能為代價來提高讀取效能。資料的冗餘副本寫入多個表中以避免昂貴的連接。一些 RDBMS(例如 PostgreSQL 和 Oracle)支援物化視圖,該視圖處理儲存冗餘資訊和保持冗餘副本一致的工作。
一旦資料透過聯合和分片等技術進行分佈,管理跨資料中心的連接就會進一步增加複雜性。非規範化可能會避免這種複雜連接的需要。
在大多數系統中,讀取數量遠多於寫入數量,比例為 100:1 甚至 1000:1。導致複雜資料庫連接的讀取可能非常昂貴,並且會在磁碟操作上花費大量時間。
SQL 調優是一個廣泛的主題,並且已經編寫了許多書籍作為參考。
進行基準測試和分析以模擬和發現瓶頸非常重要。
基準測試和分析可能會引導您進行以下最佳化。
CHAR
而不是VARCHAR
。CHAR
有效地允許快速、隨機訪問,而使用VARCHAR
時,您必須找到字串的結尾才能移動到下一個字串。TEXT
用於大文本塊,例如部落格文章。 TEXT
還允許布爾搜索。使用TEXT
欄位會導致在磁碟上儲存一個用於定位文字區塊的指標。INT
。DECIMAL
以避免浮點表示錯誤。BLOBS
,而是儲存獲取物件的位置。VARCHAR(255)
是 8 位數字中可以計數的最大字元數,通常在某些 RDBMS 中最大化位元組的使用。NOT NULL
約束以提高搜尋效能。 SELECT
、 GROUP BY
、 ORDER BY
、 JOIN
)使用索引可能會更快。NoSQL 是在鍵值儲存、文件儲存、寬列儲存或圖形資料庫中表示的資料項目的集合。資料是非規範化的,連接通常在應用程式程式碼中完成。大多數 NoSQL 儲存缺乏真正的 ACID 事務並傾向於最終一致性。
BASE通常用來描述 NoSQL 資料庫的屬性。與 CAP 定理相比,BASE 選擇可用性而不是一致性。
除了在 SQL 或 NoSQL 之間進行選擇之外,了解哪種類型的 NoSQL 資料庫最適合您的用例也很有幫助。我們將在下一節中回顧鍵值儲存、文件儲存、寬列儲存和圖形資料庫。
抽象:哈希表
鍵值儲存通常允許 O(1) 讀取和寫入,並且通常由記憶體或 SSD 支援。資料儲存可以按字典順序維護鍵,從而可以有效檢索鍵範圍。鍵值儲存可以允許儲存帶有值的元資料。
鍵值儲存提供高效能,通常用於簡單的資料模型或快速變化的數據,例如記憶體快取層。由於它們僅提供有限的操作集,因此如果需要其他操作,複雜性就會轉移到應用程式層。
鍵值儲存是更複雜系統的基礎,例如文件存儲,在某些情況下是圖形資料庫。
抽象:鍵值存儲,文件儲存為值
文件儲存以文件(XML、JSON、二進位等)為中心,其中文件儲存給定物件的所有資訊。文件儲存提供 API 或查詢語言來根據文件本身的內部結構進行查詢。請注意,許多鍵值儲存都包含用於處理值元資料的功能,從而模糊了這兩種儲存類型之間的界限。
根據底層實現,文件按集合、標籤、元資料或目錄進行組織。儘管文件可以組織或分組在一起,但文件可能具有彼此完全不同的欄位。
一些文件儲存(例如 MongoDB 和 CouchDB)也提供類似 SQL 的語言來執行複雜的查詢。 DynamoDB 支援鍵值和文件。
文件儲存提供了高度的靈活性,通常用於處理偶爾變化的資料。
資料來源:SQL 與 NoSQL,簡史
抽象:巢狀映射
ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>
寬列儲存的基本資料單位是列(名稱/值對)。列可以按列族進行分組(類似 SQL 表)。超級柱族進一步將柱族分組。您可以使用行鍵獨立存取每一列,具有相同行鍵的列形成一行。每個值都包含用於版本控制和衝突解決的時間戳記。
Google 推出了 Bigtable 作為第一個寬列存儲,影響了 Hadoop 生態系統中常用的開源 HBase,以及 Facebook 的 Cassandra。 BigTable、HBase 和 Cassandra 等儲存以字典順序維護鍵,從而允許高效率擷取選擇性鍵範圍。
寬列儲存提供高可用性和高可擴充性。它們通常用於非常大的數據集。
來源:圖資料庫
抽象:圖
在圖資料庫中,每個節點是一筆記錄,每個弧是兩個節點之間的關係。圖資料庫經過最佳化,可以表示具有許多外鍵或多對多關係的複雜關係。
圖資料庫為具有複雜關係的資料模型(例如社交網路)提供高效能。它們相對較新,尚未廣泛使用;尋找開發工具和資源可能會更加困難。許多圖表只能透過 REST API 存取。
來源:從 RDBMS 過渡到 NoSQL
SQL的原因:
使用NoSQL的原因:
非常適合 NoSQL 的範例資料:
來源:可擴展系統設計模式
快取可以縮短頁面載入時間,並減少伺服器和資料庫的負載。在這個模型中,調度程序將首先查找之前是否已經發出過請求,並嘗試找到先前的結果來返回,以節省實際執行。
資料庫通常受益於跨分區的均勻讀寫分佈。熱門商品可能會扭曲分佈,導致瓶頸。將快取放在資料庫前面可以幫助吸收不均勻的負載和流量尖峰。
快取可以位於客戶端(作業系統或瀏覽器)、伺服器端或不同的快取層。
CDN 被視為一種快取。
反向代理和快取(例如 Varnish)可以直接提供靜態和動態內容。 Web 伺服器也可以快取請求,回傳回應,而無需聯繫應用程式伺服器。
您的資料庫通常在預設配置中包含某種級別的緩存,並針對通用用例進行了最佳化。針對特定使用模式調整這些設定可以進一步提高效能。
記憶體快取(例如 Memcached 和 Redis)是應用程式和資料儲存之間的鍵值儲存。由於資料保存在 RAM 中,因此它比資料儲存在磁碟上的典型資料庫快得多。 RAM 比磁碟受到更多限制,因此最近最少使用 (LRU) 等快取失效演算法可以幫助使「冷」條目無效並將「熱」資料保留在 RAM 中。
Redis 還有以下附加功能:
您可以快取多個級別,這些級別分為兩大類:資料庫查詢和物件:
一般來說,您應該盡量避免基於檔案的緩存,因為它會使克隆和自動縮放變得更加困難。
每當您查詢資料庫時,都會將查詢哈希為鍵並將結果儲存到快取中。這種方法有過期問題:
將您的資料視為一個對象,類似於您對應用程式程式碼所做的操作。讓您的應用程式將資料庫中的資料集組裝成類別實例或資料結構:
關於快取內容的建議:
由於您只能在快取中儲存有限數量的數據,因此您需要確定哪種快取更新策略最適合您的用例。
來源:從快取到記憶體資料網格
應用程式負責從儲存中讀取和寫入。快取不直接與儲存互動。該應用程式執行以下操作:
def get_user ( self , user_id ):
user = cache . get ( "user.{0}" , user_id )
if user is None :
user = db . query ( "SELECT * FROM users WHERE user_id = {0}" , user_id )
if user is not None :
key = "user.{0}" . format ( user_id )
cache . set ( key , json . dumps ( user ))
return user
Memcached一般都是這樣使用的。
新增到快取的資料的後續讀取速度很快。快取側也稱為延遲載入。僅快取請求的數據,這避免了快取被未請求的數據填滿。
來源:可擴展性、可用性、穩定性、模式
應用程式使用快取作為主要數據存儲,向其中讀取和寫入數據,而快取則負責讀取和寫入資料庫:
申請代碼:
set_user ( 12345 , { "foo" : "bar" })
快取代碼:
def set_user ( user_id , values ):
user = db . query ( "UPDATE Users WHERE id = {0}" , user_id , values )
cache . set ( user_id , user )
由於寫入操作,直寫是一個緩慢的整體操作,但隨後讀取剛寫入的資料很快。與讀取資料相比,使用者更新資料時通常更能容忍延遲。快取中的資料並未陳舊。
來源:可擴展性、可用性、穩定性、模式
在後寫方式中,應用程式執行以下操作:
來源:從快取到記憶體資料網格
您可以將快取配置為在過期之前自動刷新任何最近存取的快取條目。
如果快取能夠準確預測將來可能需要哪些項目,那麼提前刷新可以減少延遲。
來源:規模化系統架構簡介
非同步工作流程有助於減少原本需要內聯執行的昂貴操作的請求時間。他們還可以透過提前完成耗時的工作來提供幫助,例如定期匯總數據。
訊息佇列接收、儲存和傳遞訊息。如果操作太慢而無法內聯執行,您可以使用具有以下工作流程的訊息佇列:
使用者不會被阻止,作業會在背景處理。在此期間,客戶端可以選擇執行少量處理,以使任務看起來像是已完成。例如,如果發布一條推文,該推文可以立即發佈到您的時間線,但可能需要一些時間才能將您的推文真正傳遞給您的所有追蹤者。
Redis作為簡單的訊息代理程式很有用,但訊息可能會遺失。
RabbitMQ很流行,但要求您適應“AMQP”協定並管理自己的節點。
Amazon SQS是託管的,但延遲可能很高,而且訊息可能會傳送兩次。
任務佇列接收任務及其相關數據,運行它們,然後交付它們的結果。它們可以支援調度,並可用於在背景執行計算密集型作業。
Celery支援調度,主要支援 python。
如果佇列開始顯著成長,佇列大小可能會變得大於內存,從而導致快取未命中、磁碟讀取甚至效能下降。背壓可以透過限制佇列大小來提供幫助,從而為佇列中已有的作業保持高吞吐率和良好的回應時間。一旦佇列填滿,客戶端就會收到伺服器繁忙或 HTTP 503 狀態代碼,以便稍後重試。客戶端可以稍後重試該請求,也許可以使用指數退避。
來源:OSI 7 層模型
HTTP 是一種在客戶端和伺服器之間編碼和傳輸資料的方法。它是一種請求/回應協定:客戶端發出請求,伺服器發出帶有相關內容和請求的完成狀態資訊的回應。 HTTP 是獨立的,允許請求和回應流經許多執行負載平衡、快取、加密和壓縮的中間路由器和伺服器。
基本的 HTTP 請求由動詞(方法)和資源(端點)組成。以下是常見的 HTTP 動詞:
動詞 | 描述 | 冪等* | 安全的 | 可緩存 |
---|---|---|---|---|
得到 | 讀取資源 | 是的 | 是的 | 是的 |
郵政 | 建立資源或觸發處理資料的進程 | 不 | 不 | 是,如果響應包含新鮮度訊息 |
放 | 建立或取代資源 | 是的 | 不 | 不 |
修補 | 部分更新資源 | 不 | 不 | 是,如果響應包含新鮮度訊息 |
刪除 | 刪除資源 | 是的 | 不 | 不 |
*可以多次呼叫而不會出現不同的結果。
HTTP 是依賴TCP和UDP等較低層協定的應用層協定。
來源:如何製作多人遊戲
TCP 是 IP 網路上連線導向的協定。使用握手來建立和終止連線。透過以下方式確保所有發送的資料包按原始順序到達目的地且不會損壞:
如果發送方沒有收到正確的回應,它將重新發送資料包。如果有多次超時,連接將被斷開。 TCP也實現流量控制和擁塞控制。這些保證會導致延遲,並且通常導致傳輸效率低於 UDP。
為了確保高吞吐量,Web 伺服器可以保持大量 TCP 連線打開,從而導致記憶體使用率較高。在 Web 伺服器執行緒(例如 Memcached 伺服器)之間擁有大量開放連線的成本可能會很高。除了在適用的情況下切換到 UDP 之外,連線池也能提供協助。
TCP 對於需要高可靠性但時間要求不高的應用程式非常有用。一些範例包括 Web 伺服器、資料庫資訊、SMTP、FTP 和 SSH。
在以下情況下使用 TCP over UDP:
來源:如何製作多人遊戲
UDP 是無連接的。資料報(類似於資料包)僅在資料報層級得到保證。資料報可能無法依序到達目的地,或根本無法到達目的地。 UDP不支援擁塞控制。如果沒有 TCP 支援的保證,UDP 通常更有效。
UDP 可以廣播,將資料封包傳送到子網路上的所有裝置。這對於 DHCP 很有用,因為客戶端尚未收到 IP 位址,從而阻止了 TCP 在沒有 IP 位址的情況下進行串流傳輸。
UDP 的可靠性較差,但在 VoIP、視訊聊天、串流媒體和即時多人遊戲等即時用例中效果良好。
在以下情況下使用 UDP over TCP:
來源:破解系統設計訪談
在 RPC 中,客戶端使程序在不同的位址空間(通常是遠端伺服器)上執行。這個過程的編碼就像本地過程呼叫一樣,從客戶端程式中抽像出如何與伺服器通訊的細節。遠端呼叫通常比本地呼叫更慢且可靠性更低,因此區分 RPC 呼叫和本地呼叫很有幫助。流行的 RPC 框架包括 Protobuf、Thrift 和 Avro。
RPC 是一種請求-回應協定:
RPC 呼叫範例:
GET /someoperation?data=anId
POST /anotheroperation
{
"data":"anId";
"anotherdata": "another value"
}
RPC 專注於暴露行為。出於效能原因,RPC 通常用於內部通信,因為您可以手動製作本機呼叫以更好地適合您的用例。
在以下情況下選擇本機庫(又稱 SDK):
REST之後的 HTTP API 往往更常用於公共 API。
REST 是一種強制執行客戶端/伺服器模型的架構風格,其中客戶端對伺服器管理的一組資源進行操作。伺服器提供資源的表示和可以操作或取得新的資源表示的操作。所有通訊都必須是無狀態且可快取的。
RESTful 介面有四個品質:
REST 呼叫範例:
GET /someresources/anId
PUT /someresources/anId
{"anotherdata": "another value"}
REST 專注於公開資料。它最大限度地減少了客戶端/伺服器之間的耦合,通常用於公共 HTTP API。 REST 使用更通用和統一的方法,透過 URI 公開資源,透過標頭表示,並透過 GET、POST、PUT、DELETE 和 PATCH 等動詞進行操作。由於 REST 無狀態,因此非常適合水平擴展和分區。
手術 | 遠程過程調用 | 休息 |
---|---|---|
報名 | 發布/註冊 | 郵寄/人 |
辭職 | 任職/辭職 { “人物”:“1234” } | 刪除/人/1234 |
讀懂一個人 | 取得/readPerson?personid=1234 | 取得/人/1234 |
讀取某人的物品清單 | 取得/readUsersItemsList?personid=1234 | 取得/人員/1234/項目 |
將項目新增至人員的項目中 | POST /addItemToUsersItemsList { 「人物」:「1234」; “項目”:“456” } | 發布/人/1234/項目 { “項目”:“456” } |
更新一個項目 | POST /修改項目 { 「itemid」:「456」; “鍵”:“值” } | 放置/項目/456 { “鍵”:“值” } |
刪除一個項目 | 發布/刪除項目 { “項目”:“456” } | 刪除/項目/456 |
來源:你真的知道為什麼你喜歡 REST 而不是 RPC
本節可能需要一些更新。考慮貢獻!
安全是一個廣泛的話題。除非您擁有豐富的經驗、安全背景,或正在申請需要安全知識的職位,否則您可能不需要了解更多基礎知識:
有時會要求您進行“粗略”估計。例如,您可能需要確定從磁碟產生 100 個影像縮圖需要多長時間,或者資料結構需要多少記憶體。每個程式設計師都應該知道的兩個表的冪和延遲數字是方便的參考。
Power Exact Value Approx Value Bytes
---------------------------------------------------------------
7 128
8 256
10 1024 1 thousand 1 KB
16 65,536 64 KB
20 1,048,576 1 million 1 MB
30 1,073,741,824 1 billion 1 GB
32 4,294,967,296 4 GB
40 1,099,511,627,776 1 trillion 1 TB
Latency Comparison Numbers
--------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 10,000 ns 10 us
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
HDD seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD
Read 1 MB sequentially from HDD 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Notes
-----
1 ns = 10^-9 seconds
1 us = 10^-6 seconds = 1,000 ns
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
基於上述數字的便利指標:
常見的系統設計面試問題,以及如何解決每個問題的資源連結。
問題 | 參考) |
---|---|
設計一個像 Dropbox 這樣的檔案同步服務 | youtube.com |
設計一個像Google一樣的搜尋引擎 | 隊列.acm.org stackexchange.com ardendertat.com 史丹佛大學 |
設計一個像Google一樣可擴展的網路爬蟲 | quora.com |
設計 Google 文件 | code.google.com 尼爾.弗雷澤.姓名 |
設計像 Redis 這樣的鍵值存儲 | 幻燈片共享網 |
設計一個像 Memcached 這樣的快取系統 | 幻燈片共享網 |
設計一個像亞馬遜的推薦系統 | 葫蘆網 ijcai13.org |
設計一個類似Bitly的tinyurl系統 | n00tc0d3r.blogspot.com |
設計一個像 WhatsApp 這樣的聊天應用程式 | highscalability.com |
設計一個像Instagram一樣的圖片分享系統 | highscalability.com highscalability.com |
設計 Facebook 新聞推播功能 | quora.com quora.com 幻燈片共享網 |
設計 Facebook 時間軸功能 | 臉書網 highscalability.com |
設計Facebook聊天功能 | erlang-factory.com 臉書網 |
設計一個像 Facebook 一樣的圖片搜尋功能 | 臉書網 臉書網 臉書網 |
設計像 CloudFlare 這樣的內容傳遞網絡 | 無花果分享網 |
設計一個像 Twitter 一樣的熱門話題系統 | 邁克爾諾爾.com 斯尼科洛夫.wordpress.com |
設計隨機ID產生系統 | 部落格.twitter.com github.com |
返回某個時間間隔內前 k 個請求 | cs.ucsb.edu wpi.edu |
設計一個為多個資料中心的資料提供服務的系統 | highscalability.com |
設計一款線上多人紙牌遊戲 | indieflashblog.com buildnewgames.com |
設計垃圾收集系統 | stuffwithstuff.com 華盛頓教育網 |
設計 API 速率限制器 | https://stripe.com/blog/ |
設計一個證券交易所(如納斯達克或幣安) | 簡街 Go 語言實現 實施 |
新增系統設計問題 | 貢獻 |
有關如何設計現實世界系統的文章。
資料來源:Twitter 大規模時間表
不要關注以下文章的具體細節,而是:
類型 | 系統 | 參考) |
---|---|---|
資料處理 | MapReduce - 來自 Google 的分散式資料處理 | 研究.google.com |
資料處理 | Spark - Databricks 的分散式資料處理 | 幻燈片共享網 |
資料處理 | Storm - Twitter 的分散式資料處理 | 幻燈片共享網 |
資料儲存 | Bigtable - 來自 Google 的分散式列式資料庫 | 哈佛教育網 |
資料儲存 | HBase - Bigtable 的開源實現 | 幻燈片共享網 |
資料儲存 | Cassandra - 來自 Facebook 的分散式列式資料庫 | 幻燈片共享網 |
資料儲存 | DynamoDB - 來自 Amazon 的文件導向的資料庫 | 哈佛教育網 |
資料儲存 | MongoDB - 面向文件的資料庫 | 幻燈片共享網 |
資料儲存 | Spanner - 來自 Google 的全球分散式資料庫 | 研究.google.com |
資料儲存 | Memcached - 分散式記憶體快取系統 | 幻燈片共享網 |
資料儲存 | Redis - 具有持久性和值類型的分散式記憶體快取系統 | 幻燈片共享網 |
檔案系統 | Google 檔案系統 (GFS) - 分散式檔案系統 | 研究.google.com |
檔案系統 | Hadoop 檔案系統 (HDFS) - GFS 的開源實現 | apache.org |
雜項 | Chubby - 來自 Google 的鬆散耦合分散式系統的鎖定服務 | 研究.google.com |
雜項 | Dapper - 分散式系統追蹤基礎設施 | 研究.google.com |
雜項 | Kafka - 來自 LinkedIn 的發布/訂閱訊息佇列 | 幻燈片共享網 |
雜項 | Zookeeper - 集中式基礎設施和服務,支援同步 | 幻燈片共享網 |
新增架構 | 貢獻 |
公司 | 參考) |
---|---|
亞馬遜 | 亞馬遜架構 |
辛奇卡斯特 | 每天製作 1,500 小時的音頻 |
資料篩選 | 即時資料探勘每秒 120,000 則推文 |
Dropbox | 我們如何擴充 Dropbox |
ESPN | 以每秒 100,000 duh nuh nuhs 的速度運行 |
Google架構 | |
1400 萬用戶,TB 級照片 Instagram 的力量是什麼 | |
賈斯汀電視 | Justin.Tv 的視訊直播架構 |
擴展 Facebook 的 memcached TAO:Facebook 的社交圖譜分散式資料存儲 Facebook 的照片存儲 Facebook 如何向 80 萬名同時觀看者進行直播 | |
弗利克 | Flickr 架構 |
信箱 | 6 週內從 0 到 100 萬用戶 |
Netflix | 整個 Netflix 堆疊的 360 度視角 Netflix:當你按下播放鍵時會發生什麼事? |
興趣 | 每月從 0 到數十億的頁面瀏覽量 1,800 萬訪客,成長 10 倍,12 名員工 |
嬉戲魚 | 每月有 5000 萬用戶並且還在持續成長 |
大量的魚 | PlentyOfFish 架構 |
銷售人員 | 他們如何每天處理 13 億筆交易 |
堆疊溢位 | 堆疊溢位架構 |
到到網 | 4,000 萬訪客、2 億動態頁面瀏覽量、30TB 數據 |
豆瓣 | 每月 150 億次頁面瀏覽量 |
嘰嘰喳喳 | 讓 Twitter 速度提升 10000% 使用 MySQL 每天儲存 2.5 億則推文 1.5 億活躍用戶、30 萬 QPS、22 MB/S 的消防水管 大規模時間表 Twitter 上的大數據和小數據 Twitter 的營運:用戶數量突破 1 億 Twitter 如何處理每秒 3,000 張圖片 |
優步 | Uber 如何擴展其實時市場平台 將 Uber 擴展到 2000 名工程師、1000 項服務和 8000 個 Git 儲存庫的經驗教訓 |
Facebook斥資190億美元收購的WhatsApp架構 | |
Youtube | YouTube 可擴充性 YouTube 架構 |
您正在面試的公司的架構。
您遇到的問題可能來自同一網域。
想要新增部落格?為了避免重複工作,請考慮將您的公司部落格新增至以下儲存庫:
有興趣添加一個部分或幫助完成一個正在進行的部分嗎?貢獻!
本存儲庫中提供了積分和來源。
特別感謝:
請隨時與我聯繫討論任何問題、疑問或意見。
我的聯絡資訊可以在我的 GitHub 頁面上找到。
我根據開源許可證向您提供此儲存庫中的程式碼和資源。因為這是我的個人儲存庫,所以您收到的我的程式碼和資源的許可證來自我,而不是我的雇主 (Facebook)。
Copyright 2017 Donne Martin
Creative Commons Attribution 4.0 International License (CC BY 4.0)
http://creativecommons.org/licenses/by/4.0/