想染指系統架構?你絕對不可錯過的一篇。

系統設計入門





翻譯

有興趣參與翻譯? 如下是正在進行中的翻譯:javascript

目的

學習如何設計大型系統。php

爲系統設計的面試作準備。html

學習如何設計大型系統

學習如何設計可擴展的系統將會有助於你成爲一個更好的工程師。前端

系統設計是一個很寬泛的話題。在互聯網上,關於系統設計原則的資源也是多如牛毛。java

這個倉庫就是這些資源的組織收集,它能夠幫助你學習如何構建可擴展的系統。python

從開源社區學習

這是一個不斷更新的開源項目的初期的版本。mysql

歡迎貢獻react

爲系統設計的面試作準備

在不少科技公司中,除了代碼面試,系統設計也是技術面試過程中的一個必要環節android

實踐常見的系統設計面試題而且把你的答案和例子的解答進行對照:討論,代碼和圖表。ios

面試準備的其餘主題:

抽認卡





這裏提供的抽認卡堆使用間隔重複的方法,幫助你記憶關鍵的系統設計概念。

隨時隨地均可使用。

代碼資源:互動式編程挑戰

你正在尋找資源以準備編程面試嗎?





請查看咱們的姐妹倉庫互動式編程挑戰,其中包含了一個額外的抽認卡堆:

貢獻

從社區中學習。

歡迎提交 PR 提供幫助:

  • 修復錯誤
  • 完善章節
  • 添加章節

一些還須要完善的內容放在了正在完善中

請查看貢獻指南

系統設計主題的索引

各類系統設計主題的摘要,包括優勢和缺點。每個主題都面臨着取捨和權衡

每一個章節都包含着更的資源的連接。





學習指引

基於你面試的時間線(短、中、長)去複習那些推薦的主題。

Imgur

問:對於面試來講,我須要知道這裏的全部知識點嗎?

答:不,若是隻是爲了準備面試的話,你並不須要知道全部的知識點。

在一場面試中你會被問到什麼取決於下面這些因素:

  • 你的經驗
  • 你的技術背景
  • 你面試的職位
  • 你面試的公司
  • 運氣

那些有經驗的候選人一般會被指望瞭解更多的系統設計的知識。架構師或者團隊負責人則會被指望瞭解更多除了我的貢獻以外的知識。頂級的科技公司一般也會有一次或者更多的系統設計面試。

面試會很寬泛的展開並在幾個領域深刻。這回幫助你瞭解一些關於系統設計的不一樣的主題。基於你的時間線,經驗,面試的職位和麪試的公司對下面的指導作出適當的調整。

  • 短時間 - 以系統設計主題的廣度爲目標。經過解決一些面試題來練習。
  • 中期 - 以系統設計主題的廣度初級深度爲目標。經過解決不少面試題來練習。
  • 長期 - 以系統設計主題的廣度高級深度爲目標。經過解決大部分面試題來聯繫。
短時間 中期 長期
閱讀 系統設計主題 以得到一個關於系統如何工做的寬泛的認識 :+1: :+1: :+1:
閱讀一些你要面試的公司工程博客的文章 :+1: :+1: :+1:
閱讀 真實架構 :+1: :+1: :+1:
複習 如何處理一個系統設計面試題 :+1: :+1: :+1:
完成 系統設計的面試題和解答 一些 不少 大部分
完成 面向對象設計的面試題和解答 一些 不少 大部分
複習 其它的系統設計面試題 一些 不少 大部分

如何處理一個系統設計的面試題

系統設計面試是一個開放式的對話。他們指望你去主導這個對話。

你能夠使用下面的步驟來指引討論。爲了鞏固這個過程,請使用下面的步驟完成系統設計的面試題和解答這個章節。

第一步:描述使用場景,約束和假設

把全部須要的東西彙集在一塊兒,審視問題。不停的提問,以致於咱們能夠明確使用場景和約束。討論假設。

  • 誰會使用它?
  • 他們會怎樣使用它?
  • 有多少用戶?
  • 系統的做用是什麼?
  • 系統的輸入輸出分別是什麼?
  • 咱們但願處理多少數據?
  • 咱們但願每秒鐘處理多少請求?
  • 咱們但願的讀寫比率?

第二步:創造一個高級的設計

使用全部重要的組件來描繪出一個高級的設計。

  • 畫出主要的組件和鏈接
  • 證實你的想法

第三步:設計核心組件

對每個核心組件進行詳細深刻的分析。舉例來講,若是你被問到設計一個 url 縮寫服務,開始討論:

  • 生成並儲存一個完整 url 的 hash
    • MD5Base62
    • Hash 碰撞
    • SQL 仍是 NoSQL
    • 數據庫模型
  • 將一個 hashed url 翻譯成完整的 url
    • 數據庫查找
  • API 和麪向對象設計

第四步:度量設計

確認和處理瓶頸以及一些限制。舉例來講就是你須要下面的這些來完成拓展性的議題嗎?

  • 負載均衡
  • 水平拓展
  • 緩存
  • 數據庫分片

論述可能的解決辦法和代價。每件事情須要取捨。能夠使用可拓展系統的設計原則來處理瓶頸。

信封背面的計算

你或許會被要求經過手算進行一些估算。涉及到的附錄涉及到的是下面的這些資源:

相關資源和延伸閱讀

查看下面的連接以得到咱們指望的更好的想法:

系統設計的面試題和解答

普通的系統設計面試題和相關事例的論述,代碼和圖表。

與內容有關的解答在 solutions/ 文件夾中。

問題
設計 Pastebin.com (或者 Bit.ly) 解答
設計 Twitter 時間線和搜索 (或者 Facebook feed 和搜索) 解答
設計一個網頁爬蟲 解答
設計 Mint.com 解答
爲一個社交網絡設計數據結構 解答
爲搜索引擎設計一個 key-value 儲存 解答
經過分類特性設計 Amazon 的銷售排名 解答
在 AWS 上設計一個百萬用戶級別的系統 解答
添加一個系統設計問題 貢獻

設計 Pastebin.com (或者 Bit.ly)

查看實踐與解答

Imgur

設計 Twitter 時間線和搜索 (或者 Facebook feed 和搜索)

查看實踐與解答

Imgur

設計一個網頁爬蟲

查看實踐與解答

Imgur

設計 Mint.com

查看實踐與解答

Imgur

爲一個社交網絡設計數據結構

查看實踐與解答

Imgur

爲搜索引擎設計一個 key-value 儲存

查看實踐與解答

Imgur

設計按類別分類的 Amazon 銷售排名

查看實踐與解答

Imgur

在 AWS 上設計一個百萬用戶級別的系統

查看實踐與解答

Imgur

面向對象設計的面試問題及解答

常見面向對象設計面試問題及實例討論,代碼和圖表演示。

與內容相關的解決方案在 solutions/ 文件夾中。

注:此節還在完善中

問題
設計 hash map 解決方案
設計 LRU 緩存 解決方案
設計一個呼叫中心 解決方案
設計一副牌 解決方案
設計一個停車場 解決方案
設計一個聊天服務 解決方案
設計一個環形數組 待解決
添加一個面向對象設計問題 待解決

系統設計主題:從這裏開始

不熟悉系統設計?

首先,你須要對通常性原則有一個基本的認識,知道它們是什麼,怎樣使用以及利弊。

第一步:回顧可擴展性(scalability)的視頻講座

哈佛大學可擴展性講座

  • 主題涵蓋
    • 垂直擴展(Vertical scaling)
    • 水平擴展(Horizontal scaling)
    • 緩存
    • 負載均衡
    • 數據庫複製
    • 數據庫分區

第二步:回顧可擴展性文章

可擴展性

接下來的步驟

接下來,咱們將看看高階的權衡和取捨:

  • 性能可擴展性
  • 延遲吞吐量
  • 可用性一致性

記住每一個方面都面臨取捨和權衡

而後,咱們將深刻更具體的主題,如 DNS、CDN 和負載均衡器。

性能與可擴展性

若是服務性能的增加與資源的增長是成比例的,服務就是可擴展的。一般,提升性能意味着服務於更多的工做單元,另外一方面,當數據集增加時,一樣也能夠處理更大的工做單位。1

另外一個角度來看待性能與可擴展性:

  • 若是你的系統有性能問題,對於單個用戶來講是緩慢的。
  • 若是你的系統有可擴展性問題,單個用戶較快但在高負載下會變慢。

來源及延伸閱讀

延遲與吞吐量

延遲是執行操做或運算結果所花費的時間。

吞吐量是單位時間內(執行)此類操做或運算的數量。

一般,你應該以可接受級延遲最大化吞吐量爲目標。

來源及延伸閱讀

可用性與一致性

CAP 理論





來源:再看 CAP 理論

在一個分佈式計算系統中,只能同時知足下列的兩點:

  • 一致性 ─ 每次訪問都能得到最新數據但可能會收到錯誤響應
  • 可用性 ─ 每次訪問都能收到非錯響應,但不保證獲取到最新數據
  • 分區容錯性 ─ 在任意分區網絡故障的狀況下系統仍能繼續運行

網絡並不可靠,因此你應要支持分區容錯性,並須要在軟件可用性和一致性間作出取捨。

CP ─ 一致性和分區容錯性

等待分區節點的響應可能會致使延時錯誤。若是你的業務需求須要原子讀寫,CP 是一個不錯的選擇。

AP ─ 可用性與分區容錯性

響應節點上可用數據的最近版本可能並非最新的。當分區解析完後,寫入(操做)可能須要一些時間來傳播。

若是業務需求容許最終一致性,或當有外部故障時要求系統繼續運行,AP 是一個不錯的選擇。

來源及延伸閱讀

一致性模式

有同一份數據的多份副本,咱們面臨着怎樣同步它們的選擇,以便讓客戶端有一致的顯示數據。回想 CAP 理論中的一致性定義 ─ 每次訪問都能得到最新數據但可能會收到錯誤響應

弱一致性

在寫入以後,訪問可能看到,也可能看不到(寫入數據)。盡力優化之讓其能訪問最新數據。

這種方式能夠 memcached 等系統中看到。弱一致性在 VoIP,視頻聊天和實時多人遊戲等真實用例中表現不錯。打個比方,若是你在通話中丟失信號幾秒鐘時間,當從新鏈接時你是聽不到這幾秒鐘所說的話的。

最終一致性

在寫入後,訪問最終能看到寫入數據(一般在數毫秒內)。數據被異步複製。

DNS 和 email 等系統使用的是此種方式。最終一致性在高可用性系統中效果不錯。

強一致性

在寫入後,訪問當即可見。數據被同步複製。

文件系統和關係型數據庫(RDBMS)中使用的是此種方式。強一致性在須要記錄的系統中運做良好。

來源及延伸閱讀

可用性模式

有兩種支持高可用性的模式: 故障切換(fail-over)複製(replication)

故障切換

工做到備用切換(Active-passive)

關於工做到備用的故障切換流程是,工做服務器發送週期信號給待機中的備用服務器。若是週期信號中斷,備用服務器切換成工做服務器的 IP 地址並恢復服務。

宕機時間取決於備用服務器處於「熱」待機狀態仍是須要從「冷」待機狀態進行啓動。只有工做服務器處理流量。

工做到備用的故障切換也被稱爲主從切換。

雙工做切換(Active-active)

在雙工做切換中,雙方都在管控流量,在它們之間分散負載。

若是是外網服務器,DNS 將須要對兩方都瞭解。若是是內網服務器,應用程序邏輯將須要對兩方都瞭解。

雙工做切換也能夠稱爲主主切換。

缺陷:故障切換

  • 故障切換須要添加額外硬件並增長複雜性。
  • 若是新寫入數據在能被複制到備用系統以前,工做系統出現了故障,則有可能會丟失數據。

複製

主─從複製和主─主複製

這個主題進一步探討了數據庫部分:

域名系統





來源:DNS 安全介紹

域名系統是把 www.example.com 等域名轉換成 IP 地址。

域名系統是分層次的,一些 DNS 服務器位於頂層。當查詢(域名) IP 時,路由或 ISP 提供鏈接 DNS 服務器的信息。較底層的 DNS 服務器緩存映射,它可能會由於 DNS 傳播延時而失效。DNS 結果能夠緩存在瀏覽器或操做系統中一段時間,時間長短取決於存活時間 TTL

  • NS 記錄(域名服務) ─ 指定解析域名或子域名的 DNS 服務器。
  • MX 記錄(郵件交換) ─ 指定接收信息的郵件服務器。
  • A 記錄(地址) ─ 指定域名對應的 IP 地址記錄。
  • CNAME(規範) ─ 一個域名映射到另外一個域名或 CNAME 記錄( example.com 指向 www.example.com )或映射到一個 A 記錄。

CloudFlareRoute 53 等平臺提供管理 DNS 的功能。某些 DNS 服務經過集中方式來路由流量:

  • 加權輪詢調度
    • 防止流量進入維護中的服務器
    • 在不一樣大小集羣間負載均衡
    • A/B 測試
  • 基於延遲路由
  • 基於地理位置路由

缺陷:DNS

  • 雖然說緩存能夠減輕 DNS 延遲,但鏈接 DNS 服務器仍是帶來了輕微的延遲。
  • 雖然它們一般由政府,網絡服務提供商和大公司管理,但 DNS 服務管理仍多是複雜的。
  • DNS 服務最近遭受 DDoS 攻擊,阻止不知道 Twtter IP 地址的用戶訪問 Twiiter。

來源及延伸閱讀

內容分發網絡(CDN)





來源:爲何使用 CDN

內容分發網絡(CDN)是一個全球性的代理服務器分佈式網絡,它從靠近用戶的位置提供內容。一般,HTML/CSS/JS,圖片和視頻等靜態內容由 CDN 提供,雖然亞馬遜 CloudFront 等也支持動態內容。CDN 的 DNS 解析會告知客戶端鏈接哪臺服務器。

將內容存儲在 CDN 上能夠從兩個方面來提供性能:

  • 從靠近用戶的數據中心提供資源
  • 經過 CDN 你的服務器沒必要真的處理請求

CDN 推送(push)

當你服務器上內容發生變更時,推送 CDN 接受新內容。直接推送給 CDN 並重寫 URL 地址以指向你的內容的 CDN 地址。你能夠配置內容到期時間及什麼時候更新。內容只有在更改或新增是才推送,流量最小化,但儲存最大化。

CDN 拉取(pull)

CDN 拉取是當第一個用戶請求該資源時,從服務器上拉取資源。你將內容留在本身的服務器上並重寫 URL 指向 CDN 地址。直到內容被緩存在 CDN 上爲止,這樣請求只會更慢,

存活時間(TTL)決定緩存多久時間。CDN 拉取方式最小化 CDN 上的儲存空間,但若是過時文件並在實際更改以前被拉取,則會致使冗餘的流量。

高流量站點使用 CDN 拉取效果不錯,由於只有最近請求的內容保存在 CDN 中,流量才能更平衡地分散。

缺陷:CDN

  • CDN 成本可能因流量而異,可能在權衡以後你將不會使用 CDN。
  • 若是在 TTL 過時以前更新內容,CDN 緩存內容可能會過期。
  • CDN 須要更改靜態內容的 URL 地址以指向 CDN。

來源及延伸閱讀

負載均衡器





來源:可擴展的系統設計模式

負載均衡器將傳入的請求分發到應用服務器和數據庫等計算資源。不管哪一種狀況,負載均衡器將從計算資源來的響應返回給恰當的客戶端。負載均衡器的效用在於:

  • 防止請求進入很差的服務器
  • 防止資源過載
  • 幫助消除單一的故障點

負載均衡器能夠經過硬件(昂貴)或 HAProxy 等軟件來實現。
增長的好處包括:

  • SSL 終結 ─ 解密傳入的請求並加密服務器響應,這樣的話後端服務器就沒必要再執行這些潛在高消耗運算了。
  • Session 留存 ─ 若是 Web 應用程序不追蹤會話,發出 cookie 並將特定客戶端的請求路由到同一實例。

一般會設置採用工做─備用雙工做 模式的多個負載均衡器,以避免發生故障。

負載均衡器能基於多種方式來路由流量:

四層負載均衡

四層負載均衡根據監看傳輸層的信息來決定如何分發請求。一般,這會涉及來源,目標 IP 地址和請求頭中的端口,但不包括數據包(報文)內容。四層負載均衡執行網絡地址轉換(NAT)來向上遊服務器轉發網絡數據包。

七層負載均衡器

七層負載均衡器根據監控應用層來決定怎樣分發請求。這會涉及請求頭的內容,消息和 cookie。七層負載均衡器終結網絡流量,讀取消息,作出負載均衡斷定,而後傳送給特定服務器。好比,一個七層負載均衡器能直接將視頻流量鏈接到託管視頻的服務器,同時將更敏感的用戶帳單流量引導到安全性更強的服務器。

以損失靈活性爲代價,四層負載均衡比七層負載均衡花費更少時間和計算資源,雖然這對現代商用硬件的性能影響甚微。

水平擴展

負載均衡器還能幫助水平擴展,提升性能和可用性。使用商業硬件的性價比更高,而且比在單臺硬件上垂直擴展更貴的硬件具備更高的可用性。相比招聘特定企業系統人才,招聘商業硬件方面的人才更加容易。

缺陷:水平擴展

  • 水平擴展引入了複雜度並涉及服務器複製
    • 服務器應該是無狀態的:它們也不應包含像 session 或資料圖片等與用戶關聯的數據。
    • session 能夠集中存儲在數據庫或持久化緩存(Redis、Memcached)的數據存儲區中。
  • 緩存和數據庫等下游服務器須要隨着上游服務器進行擴展,以處理更多的併發鏈接。

缺陷:負載均衡器

  • 若是沒有足夠的資源配置或配置錯誤,負載均衡器會變成一個性能瓶頸。
  • 引入負載均衡器以幫助消除單點故障但致使了額外的複雜性。
  • 單個負載均衡器會致使單點故障,但配置多個負載均衡器會進一步增長複雜性。

來源及延伸閱讀

反向代理(web 服務器)





資料來源:維基百科


反向代理是一種能夠集中地調用內部服務,並提供統一接口給公共客戶的 web 服務器。來自客戶端的請求先被反向代理服務器轉發到可響應請求的服務器,而後代理再把服務器的響應結果返回給客戶端。

帶來的好處包括:

  • 增長安全性 - 隱藏後端服務器的信息,屏蔽黑名單中的 IP,限制每一個客戶端的鏈接數。
  • 提升可擴展性和靈活性 - 客戶端只能看到反向代理服務器的 IP,這使你能夠增減服務器或者修改它們的配置。
  • 本地終結 SSL 會話 - 解密傳入請求,加密服務器響應,這樣後端服務器就沒必要完成這些潛在的高成本的操做。
    • 免除了在每一個服務器上安裝 X.509 證書的須要
  • 壓縮 - 壓縮服務器響應
  • 緩存 - 直接返回命中的緩存結果
  • 靜態內容 - 直接提供靜態內容
    • HTML/CSS/JS
    • 圖片
    • 視頻
    • 等等

負載均衡器與反向代理

  • 當你有多個服務器時,部署負載均衡器很是有用。一般,負載均衡器將流量路由給一組功能相同的服務器上。
  • 即便只有一臺 web 服務器或者應用服務器時,反向代理也有用,能夠參考上一節介紹的好處。
  • NGINX 和 HAProxy 等解決方案能夠同時支持第七層反向代理和負載均衡。

不利之處:反向代理

  • 引入反向代理會增長系統的複雜度。
  • 單獨一個反向代理服務器仍可能發生單點故障,配置多臺反向代理服務器(如故障轉移)會進一步增長複雜度。

來源及延伸閱讀

應用層





資料來源:可縮放系統構架介紹

將 Web 服務層與應用層(也被稱做平臺層)分離,能夠獨立縮放和配置這兩層。添加新的 API 只須要添加應用服務器,而沒必要添加額外的 web 服務器。

單一職責原則提倡小型的,自治的服務共同合做。小團隊經過提供小型的服務,能夠更激進地計劃增加。

應用層中的工做進程也有能夠實現異步化

微服務

與此討論相關的話題是 微服務,能夠被描述爲一系列能夠獨立部署的小型的,模塊化服務。每一個服務運行在一個獨立的線程中,經過明肯定義的輕量級機制通信,共同實現業務目標。1

例如,Pinterest 可能有這些微服務: 用戶資料、關注者、Feed 流、搜索、照片上傳等。

服務發現

ConsulEtcdZookeeper 這樣的系統能夠經過追蹤註冊名、地址、端口等信息來幫助服務互相發現對方。Health checks 能夠幫助確認服務的完整性和是否常用一個 HTTP 路徑。Consul 和 Etcd 都有一個內建的 key-value 存儲 用來存儲配置信息和其餘的共享信息。

不利之處:應用層

  • 添加由多個鬆耦合服務組成的應用層,從架構、運營、流程等層面來說將很是不一樣(相對於單體系統)。
  • 微服務會增長部署和運營的複雜度。

來源及延伸閱讀

數據庫





資料來源:擴展你的用戶數到第一個一千萬

關係型數據庫管理系統(RDBMS)

像 SQL 這樣的關係型數據庫是一系列以表的形式組織的數據項集合。

校對注:這裏做者 SQL 可能指的是 MySQL

ACID 用來描述關係型數據庫事務的特性。

  • 原子性 - 每一個事務內部全部操做要麼所有完成,要麼所有不完成。
  • 一致性 - 任何事務都使數據庫從一個有效的狀態轉換到另外一個有效狀態。
  • 隔離性 - 併發執行事務的結果與順序執行事務的結果相同。
  • 持久性 - 事務提交後,對系統的影響是永久的。

關係型數據庫擴展包括許多技術:主從複製主主複製聯合分片非規範化SQL調優





資料來源:可擴展性、可用性、穩定性、模式

主從複製

主庫同時負責讀取和寫入操做,並複製寫入到一個或多個從庫中,從庫只負責讀操做。樹狀形式的從庫再將寫入複製到更多的從庫中去。若是主庫離線,系統能夠以只讀模式運行,直到某個從庫被提高爲主庫或有新的主庫出現。

不利之處:主從複製
  • 將從庫提高爲主庫須要額外的邏輯。
  • 參考不利之處:複製中,主從複製和主主複製共同的問題。





資料來源:可擴展性、可用性、穩定性、模式

主主複製

兩個主庫都負責讀操做和寫操做,寫入操做時互相協調。若是其中一個主庫掛機,系統能夠繼續讀取和寫入。

不利之處: 主主複製
  • 你須要添加負載均衡器或者在應用邏輯中作改動,來肯定寫入哪個數據庫。
  • 多數主-主系統要麼不能保證一致性(違反 ACID),要麼由於同步產生了寫入延遲。
  • 隨着更多寫入節點的加入和延遲的提升,如何解決衝突顯得愈加重要。
  • 參考不利之處:複製中,主從複製和主主複製共同的問題。
不利之處:複製
  • 若是主庫在將新寫入的數據複製到其餘節點前掛掉,則有數據丟失的可能。
  • 寫入會被重放到負責讀取操做的副本。副本可能由於過多寫操做阻塞住,致使讀取功能異常。
  • 讀取從庫越多,須要複製的寫入數據就越多,致使更嚴重的複製延遲。
  • 在某些數據庫系統中,寫入主庫的操做能夠用多個線程並行寫入,但讀取副本只支持單線程順序地寫入。
  • 複製意味着更多的硬件和額外的複雜度。
來源及延伸閱讀

聯合





資料來源:擴展你的用戶數到第一個一千萬

聯合(或按功能劃分)將數據庫按對應功能分割。例如,你能夠有三個數據庫:論壇用戶產品,而不只是一個單體數據庫,從而減小每一個數據庫的讀取和寫入流量,減小複製延遲。較小的數據庫意味着更多適合放入內存的數據,進而意味着更高的緩存命中概率。沒有隻能串行寫入的中心化主庫,你能夠並行寫入,提升負載能力。

不利之處:聯合
  • 若是你的數據庫模式須要大量的功能和數據表,聯合的效率並很差。
  • 你須要更新應用程序的邏輯來肯定要讀取和寫入哪一個數據庫。
  • server link 從兩個庫聯結數據更復雜。
  • 聯合須要更多的硬件和額外的複雜度。
來源及延伸閱讀:聯合

分片





資料來源:可擴展性、可用性、穩定性、模式

分片將數據分配在不一樣的數據庫上,使得每一個數據庫僅管理整個數據集的一個子集。以用戶數據庫爲例,隨着用戶數量的增長,愈來愈多的分片會被添加到集羣中。

相似聯合的優勢,分片能夠減小讀取和寫入流量,減小複製並提升緩存命中率。也減小了索引,一般意味着查詢更快,性能更好。若是一個分片出問題,其餘的仍能運行,你能夠使用某種形式的冗餘來防止數據丟失。相似聯合,沒有隻能串行寫入的中心化主庫,你能夠並行寫入,提升負載能力。

常見的作法是用戶姓氏的首字母或者用戶的地理位置來分隔用戶表。

不利之處:分片
  • 你須要修改應用程序的邏輯來實現分片,這會帶來複雜的 SQL 查詢。
  • 分片不合理可能致使數據負載不均衡。例如,被頻繁訪問的用戶數據會致使其所在分片的負載相對其餘分片高。
    • 再平衡會引入額外的複雜度。基於一致性哈希的分片算法能夠減小這種狀況。
  • 聯結多個分片的數據操做更復雜。
  • 分片須要更多的硬件和額外的複雜度。

來源及延伸閱讀:分片

非規範化

非規範化試圖以寫入性能爲代價來換取讀取性能。在多個表中冗餘數據副本,以免高成本的聯結操做。一些關係型數據庫,好比 PostgreSQl 和 Oracle 支持物化視圖,能夠處理冗餘信息存儲和保證冗餘副本一致。

當數據使用諸如聯合分片等技術被分割,進一步提升了處理跨數據中心的聯結操做複雜度。非規範化能夠規避這種複雜的聯結操做。

在多數系統中,讀取操做的頻率遠高於寫入操做,比例可達到 100:1,甚至 1000:1。須要複雜的數據庫聯結的讀取操做成本很是高,在磁盤操做上消耗了大量時間。

不利之處:非規範化
  • 數據會冗餘。
  • 約束能夠幫助冗餘的信息副本保持同步,但這樣會增長數據庫設計的複雜度。
  • 非規範化的數據庫在高寫入負載下性能可能比規範化的數據庫差。
來源及延伸閱讀:非規範化

SQL 調優

SQL 調優是一個範圍很廣的話題,有不少相關的能夠做爲參考。

利用基準測試性能分析來模擬和發現系統瓶頸很重要。

  • 基準測試 - 用 ab 等工具模擬高負載狀況。
  • 性能分析 - 經過啓用如慢查詢日誌等工具來輔助追蹤性能問題。

基準測試和性能分析可能會指引你到如下優化方案。

改進模式
  • 爲了實現快速訪問,MySQL 在磁盤上用連續的塊存儲數據。
  • 使用 CHAR 類型存儲固定長度的字段,不要用 VARCHAR
    • CHAR 在快速、隨機訪問時效率很高。若是使用 VARCHAR,若是你想讀取下一個字符串,不得不先讀取到當前字符串的末尾。
  • 使用 TEXT 類型存儲大塊的文本,例如博客正文。TEXT 還容許布爾搜索。使用 TEXT 字段須要在磁盤上存儲一個用於定位文本塊的指針。
  • 使用 INT 類型存儲高達 2^32 或 40 億的較大數字。
  • 使用 DECIMAL 類型存儲貨幣能夠避免浮點數表示錯誤。
  • 避免使用 BLOBS 存儲對象,存儲存放對象的位置。
  • VARCHAR(255) 是以 8 位數字存儲的最大字符數,在某些關係型數據庫中,最大限度地利用字節。
  • 在適用場景中設置 NOT NULL 約束來提升搜索性能
使用正確的索引
  • 你正查詢(SELECTGROUP BYORDER BYJOIN)的列若是用了索引會更快。
  • 索引一般表示爲自平衡的 B 樹,能夠保持數據有序,並容許在對數時間內進行搜索,順序訪問,插入,刪除操做。
  • 設置索引,會將數據存在內存中,佔用了更多內存空間。
  • 寫入操做會變慢,由於索引須要被更新。
  • 加載大量數據時,禁用索引再加載數據,而後重建索引,這樣也許會更快。
避免高成本的聯結操做
  • 有性能須要,能夠進行非規範化。
分割數據表
  • 將熱點數據拆分到單獨的數據表中,能夠有助於緩存。
調優查詢緩存
來源及延伸閱讀

NoSQL

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 訪問。

相關資源和延伸閱讀:圖

來源及延伸閱讀:NoSQL

SQL 仍是 NoSQL





資料來源:從 RDBMS 轉換到 NoSQL

選取 SQL 的緣由:

  • 結構化數據
  • 嚴格的模式
  • 關係型數據
  • 須要複雜的聯結操做
  • 事務
  • 清晰的擴展模式
  • 既有資源更豐富:開發者、社區、代碼庫、工具等
  • 經過索引進行查詢很是快

選取 NoSQL 的緣由:

  • 半結構化數據
  • 動態或靈活的模式
  • 非關係型數據
  • 不須要複雜的聯結操做
  • 存儲 TB (甚至 PB)級別的數據
  • 高數據密集的工做負載
  • IOPS 高吞吐量

適合 NoSQL 的示例數據:

  • 埋點數據和日誌數據
  • 排行榜或者得分數據
  • 臨時數據,如購物車
  • 頻繁訪問的(「熱」)表
  • 元數據/查找表
來源及延伸閱讀:SQL 或 NoSQL





資料來源:可擴展的系統設計模式

緩存能夠提升頁面加載速度,並能夠減小服務器和數據庫的負載。在這個模型中,分發器先查看請求以前是否被響應過,若是有則將以前的結果直接返回,來省掉真正的處理。

數據庫分片均勻分佈的讀取是最好的。可是熱門數據會讓讀取分佈不均勻,這樣就會形成瓶頸,若是在數據庫前加個緩存,就會抹平不均勻的負載和突發流量對數據庫的影響。

客戶端緩存

緩存能夠位於客戶端(操做系統或者瀏覽器),服務端或者不一樣的緩存層。

CDN 緩存

CDN 也被視爲一種緩存。

Web 服務器緩存

反向代理和緩存(好比 Varnish)能夠直接提供靜態和動態內容。Web 服務器一樣也能夠緩存請求,返回相應結果而沒必要鏈接應用服務器。

數據庫緩存

數據庫的默認配置中一般包含緩存級別,針對通常用例進行了優化。調整配置,在不一樣狀況下使用不一樣的模式能夠進一步提升性能。

應用緩存

基於內存的緩存好比 Memcached 和 Redis 是應用程序和數據存儲之間的一種鍵值存儲。因爲數據保存在 RAM 中,它比存儲在磁盤上的典型數據庫要快多了。RAM 比磁盤限制更多,因此例如 least recently used (LRU)緩存無效算法能夠將「熱門數據」放在 RAM 中,而對一些比較「冷門」的數據不作處理。

Redis 有下列附加功能:

  • 持久性選項
  • 內置數據結構好比有序集合和列表

有多個緩存級別,分爲兩大類:數據庫查詢對象

  • 行級別
  • 查詢級別
  • 完整的可序列化對象
  • 徹底渲染的 HTML

通常來講,你應該儘可能避免基於文件的緩存,由於這使得複製和自動縮放很困難。

數據庫查詢級別的緩存

當你查詢數據庫的時候,將查詢語句的哈希值與查詢結果存儲到緩存中。這種方法會遇到如下問題:

  • 很難用複雜的查詢刪除已緩存結果。
  • 若是一條數據好比表中某條數據的一項被改變,則須要刪除全部可能包含已更改項的緩存結果。

對象級別的緩存

將您的數據視爲對象,就像對待你的應用代碼同樣。讓應用程序將數據從數據庫中組合到類實例或數據結構中:

  • 若是對象的基礎數據已經更改了,那麼從緩存中刪掉這個對象。
  • 容許異步處理:workers 經過使用最新的緩存對象來組裝對象。

建議緩存的內容:

  • 用戶會話
  • 徹底渲染的 Web 頁面
  • 活動流
  • 用戶圖數據

什麼時候更新緩存

因爲你只能在緩存中存儲有限的數據,因此你須要選擇一個適用於你用例的緩存更新策略。

緩存模式





資料來源:從緩存到內存數據網格

應用從存儲器讀寫。緩存不和存儲器直接交互,應用執行如下操做:

  • 在緩存中查找記錄,若是所需數據不在緩存中
  • 從數據庫中加載所需內容
  • 將查找到的結果存儲到緩存中
  • 返回所需內容
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 一般用這種方式使用。

添加到緩存中的數據讀取速度很快。緩存模式也稱爲延遲加載。只緩存所請求的數據,這避免了沒有被請求的數據佔滿了緩存空間。

緩存的缺點:
  • 請求的數據若是不在緩存中就須要通過三個步驟來獲取數據,這會致使明顯的延遲。
  • 若是數據庫中的數據更新了會致使緩存中的數據過期。這個問題須要經過設置 TTL 強制更新緩存或者直寫模式來緩解這種狀況。
  • 當一個節點出現故障的時候,它將會被一個新的節點替代,這增長了延遲的時間。

直寫模式





資料來源:可擴展性、可用性、穩定性、模式

應用使用緩存做爲主要的數據存儲,將數據讀寫到緩存中,而緩存負責從數據庫中讀寫數據。

  • 應用向緩存中添加/更新數據
  • 緩存同步地寫入數據存儲
  • 返回所需內容

應用代碼:

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)複製代碼

因爲存寫操做因此直寫模式總體是一種很慢的操做,可是讀取剛寫入的數據很快。相比讀取數據,用戶一般比較能接受更新數據時速度較慢。緩存中的數據不會過期。

直寫模式的缺點:
  • 因爲故障或者縮放而建立的新的節點,新的節點不會緩存,直到數據庫更新爲止。緩存應用直寫模式能夠緩解這個問題。
  • 寫入的大多數數據可能永遠都不會被讀取,用 TTL 能夠最小化這種狀況的出現。

回寫模式





資料來源:可擴展性、可用性、穩定性、模式

在回寫模式中,應用執行如下操做:

  • 在緩存中增長或者更新條目
  • 異步寫入數據,提升寫入性能。
回寫模式的缺點:
  • 緩存可能在其內容成功存儲以前丟失數據。
  • 執行直寫模式比緩存或者回寫模式更復雜。

刷新





資料來源:從緩存到內存數據網格

你能夠將緩存配置成在到期以前自動刷新最近訪問過的內容。

若是緩存能夠準確預測未來可能請求哪些數據,那麼刷新可能會致使延遲與讀取時間的下降。

刷新的缺點:
  • 不能準確預測到將來須要用到的數據可能會致使性能不如不使用刷新。

緩存的缺點:

  • 須要保持緩存和真實數據源之間的一致性,好比數據庫根據緩存無效
  • 須要改變應用程序好比增長 Redis 或者 memcached。
  • 無效緩存是個難題,何時更新緩存是與之相關的複雜問題。

相關資源和延伸閱讀

異步





資料來源:可縮放系統構架介紹

異步工做流有助於減小那些本來順序執行的請求時間。它們能夠經過提早進行一些耗時的工做來幫助減小請求時間,好比按期彙總數據。

消息隊列

消息隊列接收,保留和傳遞消息。若是按順序執行操做太慢的話,你能夠使用有如下工做流的消息隊列:

  • 應用程序將做業發佈到隊列,而後通知用戶做業狀態
  • 一個 worker 從隊列中取出該做業,對其進行處理,而後顯示該做業完成

不去阻塞用戶操做,做業在後臺處理。在此期間,客戶端可能會進行一些處理使得看上去像是任務已經完成了。例如,若是要發送一條推文,推文可能會立刻出如今你的時間線上,可是可能須要一些時間才能將你的推文推送到你的全部關注者那裏去。

Redis 是一個使人滿意的簡單的消息代理,可是消息有可能會丟失。

RabbitMQ 很受歡迎可是要求你適應「AMQP」協議而且管理你本身的節點。

Amazon SQS 是被託管的,但可能具備高延遲,而且消息可能會被傳送兩次。

任務隊列

任務隊列接收任務及其相關數據,運行它們,而後傳遞其結果。 它們能夠支持調度,並可用於在後臺運行計算密集型做業。

Celery 支持調度,主要是用 Python 開發的。

背壓

若是隊列開始明顯增加,那麼隊列大小可能會超過內存大小,致使高速緩存未命中,磁盤讀取,甚至性能更慢。背壓能夠經過限制隊列大小來幫助咱們,從而爲隊列中的做業保持高吞吐率和良好的響應時間。一旦隊列填滿,客戶端將獲得服務器忙活着 HTTP 503 狀態碼,以便稍後重試。客戶端能夠在稍後時間重試該請求,也許是指數退避

異步的缺點:

  • 簡單的計算和實時工做流等用例可能更適用於同步操做,由於引入隊列可能會增長延遲和複雜性。

相關資源和延伸閱讀

通信





資料來源:OSI 7層模型

超文本傳輸協議(HTTP)

HTTP 是一種在客戶端和服務器之間編碼和傳輸數據的方法。它是一個請求/響應協議:客戶端和服務端針對相關內容和完成狀態信息的請求和響應。HTTP 是獨立的,容許請求和響應流經許多執行負載均衡,緩存,加密和壓縮的中間路由器和服務器。

一個基本的 HTTP 請求由一個動詞(方法)和一個資源(端點)組成。 如下是常見的 HTTP 動詞:

動詞 描述 *冪等 安全性 可緩存
GET 讀取資源 Yes Yes Yes
POST 建立資源或觸發處理數據的進程 No No Yes,若是迴應包含刷新信息
PUT 建立或替換資源 Yes No No
PATCH 部分更新資源 No No Yes,若是迴應包含刷新信息
DELETE 刪除資源 Yes No No

屢次執行不會產生不一樣的結果

HTTP 是依賴於較低級協議(如 TCPUDP)的應用層協議。

來源及延伸閱讀:HTTP

傳輸控制協議(TCP)





資料來源:如何製做多人遊戲

TCP 是經過 IP 網絡的面向鏈接的協議。 使用握手創建和斷開鏈接。 發送的全部數據包保證以原始順序到達目的地,用如下措施保證數據包不被損壞:

若是發送者沒有收到正確的響應,它將從新發送數據包。若是屢次超時,鏈接就會斷開。TCP 實行流量控制)和擁塞控制。這些確保措施會致使延遲,並且一般致使傳輸效率比 UDP 低。

爲了確保高吞吐量,Web 服務器能夠保持大量的 TCP 鏈接,從而致使高內存使用。在 Web 服務器線程間擁有大量開放鏈接可能開銷巨大,消耗資源過多,也就是說,一個 memcached 服務器。鏈接池 能夠幫助除了在適用的狀況下切換到 UDP。

TCP 對於須要高可靠性但時間緊迫的應用程序頗有用。好比包括 Web 服務器,數據庫信息,SMTP,FTP 和 SSH。

如下狀況使用 TCP 代替 UDP:

  • 你須要數據無缺無損。
  • 你想對網絡吞吐量自動進行最佳評估。

用戶數據報協議(UDP)





資料來源:如何製做多人遊戲

UDP 是無鏈接的。數據報(相似於數據包)只在數據報級別有保證。數據報可能會無序的到達目的地,也有可能會遺失。UDP 不支持擁塞控制。雖然不如 TCP 那樣有保證,但 UDP 一般效率更高。

UDP 能夠經過廣播將數據報發送至子網內的全部設備。這對 DHCP 頗有用,由於子網內的設備尚未分配 IP 地址,而 IP 對於 TCP 是必須的。

UDP 可靠性更低但適合用在網絡電話、視頻聊天,流媒體和實時多人遊戲上。

如下狀況使用 UDP 代替 TCP:

  • 你須要低延遲
  • 相對於數據丟失更糟的是數據延遲
  • 你想實現本身的錯誤校訂方法

來源及延伸閱讀:TCP 與 UDP

遠程過程調用協議(RPC)





Source: Crack the system design interview

在 RPC 中,客戶端會去調用另外一個地址空間(一般是一個遠程服務器)裏的方法。調用代碼看起來就像是調用的是一個本地方法,客戶端和服務器交互的具體過程被抽象。遠程調用相對於本地調用通常較慢並且可靠性更差,所以區分二者是有幫助的。熱門的 RPC 框架包括 ProtobufThriftAvro

RPC 是一個「請求-響應」協議:

  • 客戶端程序 ── 調用客戶端存根程序。就像調用本地方法同樣,參數會被壓入棧中。
  • 客戶端 stub 程序 ── 將請求過程的 id 和參數打包進請求信息中。
  • 客戶端通訊模塊 ── 將信息從客戶端發送至服務端。
  • 服務端通訊模塊 ── 將接受的包傳給服務端存根程序。
  • 服務端 stub 程序 ── 將結果解包,依據過程 id 調用服務端方法並將參數傳遞過去。

RPC 調用示例:

GET /someoperation?data=anId

POST /anotheroperation
{
  "data":"anId";
  "anotherdata": "another value"
}複製代碼

RPC 專一於暴露方法。RPC 一般用於處理內部通信的性能問題,這樣你能夠手動處理本地調用以更好的適應你的狀況。

當如下狀況時選擇本地庫(也就是 SDK):

  • 你知道你的目標平臺。
  • 你想控制如何訪問你的「邏輯」。
  • 你想對發生在你的庫中的錯誤進行控制。
  • 性能和終端用戶體驗是你最關心的事。

遵循 REST 的 HTTP API 每每更適用於公共 API。

缺點:RPC

  • RPC 客戶端與服務實現捆綁地很緊密。
  • 一個新的 API 必須在每個操做或者用例中定義。
  • RPC 很難調試。
  • 你可能沒辦法很方便的去修改現有的技術。舉個例子,若是你但願在 Squid 這樣的緩存服務器上確保 RPC 被正確緩存的話可能須要一些額外的努力了。

表述性狀態轉移(REST)

REST 是一種強制的客戶端/服務端架構設計模型,客戶端基於服務端管理的一系列資源操做。服務端提供修改或獲取資源的接口。全部的通訊必須是無狀態和可緩存的。

RESTful 接口有四條規則:

  • 標誌資源(HTTP 裏的 URI) ── 不管什麼操做都使用同一個 URI。
  • 表示的改變(HTTP 的動做) ── 使用動做, headers 和 body。
  • 可自我描述的錯誤信息(HTTP 中的 status code) ── 使用狀態碼,不要從新造輪子。
  • HATEOAS(HTTP 中的HTML 接口) ── 你的 web 服務器應該可以經過瀏覽器訪問。

REST 請求的例子:

GET /someresources/anId

PUT /someresources/anId
{"anotherdata": "another value"}複製代碼

REST 關注於暴露數據。它減小了客戶端/服務端的耦合程度,常常用於公共 HTTP API 接口設計。REST 使用更一般與規範化的方法來經過 URI 暴露資源,經過 header 來表述並經過 GET、POST、PUT、DELETE 和 PATCH 這些動做來進行操做。由於無狀態的特性,REST 易於橫向擴展和隔離。

缺點:REST

  • 因爲 REST 將重點放在暴露數據,因此當資源不是天然組織的或者結構複雜的時候它可能沒法很好的適應。舉個例子,返回過去一小時中與特定事件集匹配的更新記錄這種操做就很難表示爲路徑。使用 REST,可能會使用 URI 路徑,查詢參數和可能的請求體來實現。
  • REST 通常依賴幾個動做(GET、POST、PUT、DELETE 和 PATCH),但有時候僅僅這些無法知足你的須要。舉個例子,將過時的文檔移動到歸檔文件夾裏去,這樣的操做可能無法簡單的用上面這幾個 verbs 表達。
  • 爲了渲染單個頁面,獲取被嵌套在層級結構中的複雜資源須要客戶端,服務器之間屢次往返通訊。例如,獲取博客內容及其關聯評論。對於使用不肯定網絡環境的移動應用來講,這些屢次往返通訊是很是麻煩的。
  • 隨着時間的推移,更多的字段可能會被添加到 API 響應中,較舊的客戶端將會接收到全部新的數據字段,即便是那些它們不須要的字段,結果它會增長負載大小並引發更大的延遲。

RPC 與 REST 比較

操做 RPC REST
註冊 POST /signup POST /persons
註銷 POST /resign
{
"personid": "1234"
}
DELETE /persons/1234
讀取用戶信息 GET /readPerson?personid=1234 GET /persons/1234
讀取用戶物品列表 GET /readUsersItemsList?personid=1234 GET /persons/1234/items
向用戶物品列表添加一項 POST /addItemToUsersItemsList
{
"personid": "1234";
"itemid": "456"
}
POST /persons/1234/items
{
"itemid": "456"
}
更新一個物品 POST /modifyItem
{
"itemid": "456";
"key": "value"
}
PUT /items/456
{
"key": "value"
}
刪除一個物品 POST /removeItem
{
"itemid": "456"
}
DELETE /items/456


資料來源:你真的知道你爲何更喜歡 REST 而不是 RPC 嗎

來源及延伸閱讀:REST 與 RPC

安全

這一部分須要更多內容。一塊兒來吧

安全是一個寬泛的話題。除非你有至關的經驗、安全方面背景或者正在申請的職位要求安全知識,你不須要了解安全基礎知識之外的內容:

  • 在運輸和等待過程當中加密
  • 對全部的用戶輸入和從用戶那裏發來的參數進行處理以防止 XSSSQL 注入
  • 使用參數化的查詢來防止 SQL 注入。
  • 使用最小權限原則

來源及延伸閱讀

附錄

一些時候你會被要求作出保守估計。好比,你可能須要估計從磁盤中生成 100 張圖片的縮略圖須要的時間或者一個數據結構須要多少的內存。2 的次方表每一個開發者都須要知道的一些時間數據(譯註:OSChina 上有這篇文章的譯文)都是一些很方便的參考資料。

2 的次方表

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                          100   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
Disk 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 disk    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複製代碼

基於上述數字的指標:

  • 從磁盤以 30 MB/s 的速度順序讀取
  • 以 100 MB/s 從 1 Gbps 的以太網順序讀取
  • 從 SSD 以 1 GB/s 的速度讀取
  • 以 4 GB/s 的速度從主存讀取
  • 每秒能繞地球 6-7 圈
  • 數據中心內每秒有 2,000 次往返

延遲數可視化

來源及延伸閱讀

其它的系統設計面試題

常見的系統設計面試問題,給出瞭如何解決的方案連接

問題 引用
設計相似於 Dropbox 的文件同步服務 youtube.com
設計相似於 Google 的搜索引擎 queue.acm.org
stackexchange.com
ardendertat.com
stanford.edu
設計相似於 Google 的可擴展網絡爬蟲 quora.com
設計 Google 文檔 code.google.com
neil.fraser.name
設計相似 Redis 的建值存儲 slideshare.net
設計相似 Memcached 的緩存系統 slideshare.net
設計相似亞馬遜的推薦系統 hulu.com
ijcai13.org
設計相似 Bitly 的短連接系統 n00tc0d3r.blogspot.com
設計相似 WhatsApp 的聊天應用 highscalability.com
設計相似 Instagram 的圖片分享系統 highscalability.com
highscalability.com
設計 Facebook 的新聞推薦方法 quora.com
quora.com
slideshare.net
設計 Facebook 的時間線系統 facebook.com
highscalability.com
設計 Facebook 的聊天系統 erlang-factory.com
facebook.com
設計相似 Facebook 的圖表搜索系統 facebook.com
facebook.com
facebook.com
設計相似 CloudFlare 的內容傳遞網絡 cmu.edu
設計相似 Twitter 的熱門話題系統 michael-noll.com
snikolov .wordpress.com
設計一個隨機 ID 生成系統 blog.twitter.com
github.com
返回必定時間段內次數前 k 高的請求 ucsb.edu
wpi.edu
設計一個數據源於多個數據中心的服務系統 highscalability.com
設計一個多人網絡卡牌遊戲 indieflashblog.com
buildnewgames.com
設計一個垃圾回收系統 stuffwithstuff.com
washington.edu
添加更多的系統設計問題 貢獻

真實架構

關於現實中真實的系統是怎麼設計的文章。





Source: Twitter timelines at scale

不要專一於如下文章的細節,專一於如下方面:

  • 發現這些文章中的共同的原則、技術和模式。
  • 學習每一個組件解決哪些問題,什麼狀況下使用,什麼狀況下不適用
  • 複習學過的文章
類型 系統 引用
Data processing MapReduce - Google的分佈式數據處理 research.google.com
Data processing Spark - Databricks 的分佈式數據處理 slideshare.net
Data processing Storm - Twitter 的分佈式數據處理 slideshare.net
Data store Bigtable - Google 的列式數據庫 harvard.edu
Data store HBase - Bigtable 的開源實現 slideshare.net
Data store Cassandra - Facebook 的列式數據庫 slideshare.net
Data store DynamoDB - Amazon 的文檔數據庫 harvard.edu
Data store MongoDB - 文檔數據庫 slideshare.net
Data store Spanner - Google 的全球分佈數據庫 research.google.com
Data store Memcached - 分佈式內存緩存系統 slideshare.net
Data store Redis - 可以持久化及具備值類型的分佈式內存緩存系統 slideshare.net
File system Google File System (GFS) - 分佈式文件系統 research.google.com
File system Hadoop File System (HDFS) - GFS 的開源實現 apache.org
Misc Chubby - Google 的分佈式系統的低耦合鎖服務 research.google.com
Misc Dapper - 分佈式系統跟蹤基礎設施 research.google.com
Misc Kafka - LinkedIn 的發佈訂閱消息系統 slideshare.net
Misc Zookeeper - 集中的基礎架構和協調服務 slideshare.net
添加更多 貢獻

公司的系統架構

Company Reference(s)
Amazon Amazon 的架構
Cinchcast 天天產生 1500 小時的音頻
DataSift 每秒實時挖掘 120000 條 tweet
DropBox 咱們如何縮放 Dropbox
ESPN 每秒操做 100000 次
Google Google 的架構
Instagram 1400 萬用戶,達到兆級別的照片存儲
是什麼在驅動 Instagram
Justin.tv Justin.Tv 的直播廣播架構
Facebook Facebook 的可擴展 memcached
TAO: Facebook 社交圖的分佈式數據存儲
Facebook 的圖片存儲
Flickr Flickr 的架構
Mailbox 在 6 周內從 0 到 100 萬用戶
Pinterest 從零到每個月數十億的瀏覽量
1800 萬訪問用戶,10 倍增加,12 名員工
Playfish 月用戶量 5000 萬並在不斷增加
PlentyOfFish PlentyOfFish 的架構
Salesforce 他們天天如何處理 13 億筆交易
Stack Overflow Stack Overflow 的架構
TripAdvisor 40M 訪問者,200M 頁面瀏覽量,30TB 數據
Tumblr 每個月 150 億的瀏覽量
Twitter Making Twitter 10000 percent faster
天天使用 MySQL 存儲2.5億條 tweet
150M 活躍用戶,300K QPS,22 MB/S 的防火牆
可擴展時間表
Twitter 的大小數據
Twitter 的行爲:規模超過 1 億用戶
Uber Uber 如何擴展本身的實時化市場
WhatsApp Facebook 用 190 億美圓購買 WhatsApp 的架構
YouTube YouTube 的可擴展性
YouTube 的架構

公司工程博客

你即將面試的公司的架構

你面對的問題可能就來自於一樣領域

來源及延伸閱讀

正在完善中

有興趣加入添加一些部分或者幫助完善某些部分嗎?加入進來吧

  • 使用 MapReduce 進行分佈式計算
  • 一致性哈希
  • 直接存儲器訪問(DMA)控制器
  • 貢獻

致謝

整個倉庫都提供了證書和源

特別鳴謝:

聯繫方式

歡迎聯繫我討論本文的不足、問題或者意見。

能夠在個人 GitHub 主頁上找到個人聯繫方式

許可

Creative Commons Attribution 4.0 International License (CC BY 4.0)

http://creativecommons.org/licenses/by/4.0/複製代碼

掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃

相關文章
相關標籤/搜索