GitHub標星163K,大廠高級研發必備的系統設計指南
學習本文可以有以下收獲
1、了解如何設計大型系統
2、拿捏面試
面試中我們常常被問到系統設計這一塊的問題,那么作為系統設計的新手,我們首先需要對通用原則具有基本的了解,知道它們是什么,怎么使用它們以及它們的缺點。話不多說,直接進入正題。
- 垂直縮放
- 水平縮放
- 緩存
- 負載均衡
- 數據庫復制
- 數據庫分區
- 涵蓋的內容:
- 首先可以觀看可擴展性視頻講座哈佛可擴展性講座https://www.youtube.com/watch?v=-W9F__D3oY4
- 查看可擴展性文章可擴展性http://www.lecloud.net/tagged/scalability/chrono當我們學習完上面的知識后,那么接下來我們需要更高的層次去權衡
- 性能與可擴展性
- 延遲與吞吐量
- 可用性與一致性
- 克隆
- 數據庫
- 緩存
- 異步
- 涵蓋的主題
性能與可擴展性
如果服務以與添加的資源成比例的方式提高性能,則服務是**可擴展的。**通常,提高性能意味著服務更多的工作單元,但也可以處理更大的工作單元,例如當數據集增長時。
另一種查看性能與可擴展性的方法:
- 如果您有性能問題,您的系統對于單個用戶來說很慢。
- 如果您有可擴展性問題,您的系統對于單個用戶來說速度很快,但在重負載下速度很慢。
我們可以進一步的閱讀了解
- 了解延遲與吞吐量
??https://community.cadence.com/cadence_blogs_8/b/sd/archive/2010/09/13/understanding-latency-vs-throughput
- 可擴展性、可用性、穩定性、模式
- ??http://www.slideshare.net/jboner/scalability-availability-stability-patterns/
延遲與吞吐量
延遲是執行某些操作或產生某些結果的時間。
吞吐量是單位時間內此類操作或結果的數量。
通常,您應該以可接受延遲的最大吞吐量為目標。
深入學習可以進一步閱讀
- 了解延遲與吞吐量
??https://community.cadence.com/cadence_blogs_8/b/sd/archive/2010/09/13/understanding-latency-vs-throughput
可用性與一致性
CAP
資料來源(重新審視CAP定理):http://robertgreiner.com/2014/08/cap-theorem-revisited
在分布式計算機系統中,您只能支持以下兩種保證:
- 一致性- 每次讀取都會收到最近的寫入或錯誤
- 可用性- 每個請求都會收到響應,但不保證它包含最新版本的信息
- 分區容限- 盡管由于網絡故障導致任意分區,系統仍繼續運行
網絡不可靠,因此您需要支持分區容錯。您需要在一致性和可用性之間進行軟件權衡。
CP - 一致性和分區容錯
等待來自分區節點的響應可能會導致超時錯誤。如果您的業務需要原子讀寫,CP 是一個不錯的選擇。
AP - 可用性和分區容錯
響應返回任何節點上可用的最容易獲得的數據版本,這可能不是最新的。解析分區后,寫入可能需要一些時間才能傳播。
如果業務需求允許最終的一致性,或者當系統需要在外部錯誤的情況下繼續工作時,AP 是一個不錯的選擇。
進一步閱讀:
- 重新審視 CAP 定理
??http://robertgreiner.com/2014/08/cap-theorem-revisited/)
- CAP 定理的簡單英文介紹
??http://ksat.me/a-plain-english-introduction-to-cap-theorem
- CAP 常見問題
??https://github.com/henryr/cap-fa
- CAP 定理
??https://www.youtube.com/watch?v=k-Yaq8AHlF
一致性
擁有一致的數據視圖。回想一下CAP 定理中一致性定義——每次讀取都會收到最近的寫入或錯誤。
弱一致性
寫入后,讀取可能會或可能不會看到它。采取了盡力而為的方法。
這種方法見于 memcached 等系統。弱一致性適用于實時用例,例如 VoIP、視頻聊天和實時多人游戲。例如,如果您正在接聽電話并在幾秒鐘內無法接收信號,那么當您重新連接時,您將聽不到在連接中斷期間所說的內容。
最終一致性
寫入后,讀取最終會看到它(通常在幾毫秒內)。數據是異步復制的。
這種方法見于 DNS 和電子郵件等系統。最終一致性在高可用性系統中運行良好。
強一致性
寫入后,讀取將看到它。數據同步復制。
這種方法出現在文件系統和 RDBMS 中。強一致性在需要事務的系統中運行良好。
到這里我們可以進一步閱讀
- 跨數據中心的交易
??http://snarfed.org/transactions_across_datacenters_io.html
可用性模式
支持高可用性有兩種互補模式:故障轉移和復制。
故障轉移
主動-被動
使用主動-被動故障轉移,心跳會在備用的主動和被動服務器之間發送。如果心跳中斷,則被動服務器接管主動服務器的 IP 地址并恢復服務。
停機時間的長短取決于被動服務器是否已經在“熱”備用狀態下運行,或者它是否需要從“冷”備用狀態啟動。只有活動服務器處理流量。
主動-被動故障轉移也可以稱為主從故障轉移。
主動-主動
在主動-主動中,兩臺服務器都在管理流量,在它們之間分散負載。
如果服務器面向公眾,則 DNS 需要了解兩臺服務器的公共 IP。如果服務器是面向內部的,則應用程序邏輯需要了解兩臺服務器。
主動-主動故障轉移也可以稱為主-主故障轉移。
缺點:故障轉移
- 故障轉移增加了更多的硬件和額外的復雜性。
- 如果主動系統在任何新寫入的數據可以復制到被動系統之前發生故障,則可能會丟失數據。
復制
主從復制和主主復制
數據庫部分將進一步討論該主題:
- 主從復制
??https://github.com/donnemartin/system-design-primer#master-slave-replication
- 主主復制
??https://github.com/donnemartin/system-design-primer#master-master-replication
分片
分片將數據分布在不同的數據庫中,這樣每個數據庫只能管理數據的一個子集。以用戶數據庫為例,隨著用戶數量的增加,集群中會添加更多的分片。
分片導致更少的讀寫流量、更少的復制和更多的緩存命中。索引大小也減少了,這通常會通過更快的查詢來提高性能。如果一個分片出現故障,其他分片仍然可以運行,盡管您需要添加某種形式的復制以避免數據丟失。與聯邦一樣,沒有單個中央主控序列化寫入,允許您并行寫入并增加吞吐量。
對用戶表進行分片的常用方法是通過用戶的姓氏首字母或用戶的地理位置。
缺點:分片
- 再平衡增加了額外的復雜性。基于一致性哈希的分片功能可以減少傳輸的數據量。
- 您需要更新應用程序邏輯以使用分片,這可能會導致復雜的 SQL 查詢。
- 分片中的數據分布可能會變得不平衡。例如,與其他分片相比,分片上的一組高級用戶可能會導致該分片的負載增加。
- 連接來自多個分片的數據更加復雜。
- 分片增加了更多的硬件和額外的復雜性。
域名系統
域名系統 (DNS) 將諸如www.example.com之類的域名轉換為 IP 地址。
DNS 是分層的,頂層有一些權威服務器。您的路由器或 ISP 提供有關在進行查找時要聯系的 DNS 服務器的信息。較低級別的 DNS 服務器緩存映射,這可能由于 DNS 傳播延遲而變得陳舊。DNS 結果也可以由您的瀏覽器或操作系統緩存一段時間,由生存時間 (TTL)確定。
NS 記錄(名稱服務器) - 為您的域/子域指定 DNS 服務器。
MX 記錄(郵件交換) - 指定接受郵件的郵件服務器。
記錄(地址) - 將名稱指向 IP 地址。
CNAME(規范) - 將名稱指向另一個名稱或CNAME(example.com 到www.example.com)或A記錄。
CloudFlare和Route 53等服務提供托管 DNS 服務。一些 DNS 服務可以通過各種方法路由流量:
加權循環
- 防止流量進入維護中的服務器
- 不同集群大小之間的平衡
- A/B 測試
基于延遲
基于地理位置
DNS的缺點
訪問DNS服務器會帶來輕微的延遲,盡管上述緩存可以緩解這種延遲。DNS服務器管理可能很復雜,通常由政府、ISP 和大公司管理。DNS服務最近受到DDoS 攻擊,阻止用戶在不知道 Twitter 的 IP 地址的情況下訪問 Twitter 等網站。
內容網絡分發
來源(為什么要使用CDN):https://www.creative-artworks.eu/why-use-a-content-delivery-network-cdn/
內容交付網絡 (CDN) 是一個全球分布的代理服務器網絡,從更靠近用戶的位置提供內容。通常,靜態文件(如 HTML/CSS/JS、照片和視頻)從 CDN 提供,盡管一些 CDN(如 Amazon 的 CloudFront)支持動態內容。該站點的 DNS 解析將告訴客戶端要聯系哪個服務器。
從 CDN 提供內容可以通過兩種方式顯著提高性能:
- 用戶從靠近他們的數據中心接收內容
- 您的服務器不必為 CDN 滿足的請求提供服務
推送 CDN
每當您的服務器發生更改時,推送 CDN 都會接收新內容。您對提供內容、直接上傳到 CDN 以及重寫 URL 以指向 CDN 負全部責任。您可以配置內容何時過期以及何時更新。僅在內容是新的或更改時才上傳內容,從而最大限度地減少流量,但最大限度地增加存儲空間。
流量較少的站點或內容不經常更新的站點可以很好地與推送 CDN 配合使用。內容被放置在 CDN 上一次,而不是定期重新拉取。
拉取 CDN
當第一個用戶請求內容時,拉取 CDN 從您的服務器中獲取新內容。您將內容留在服務器上并重寫 URL 以指向 CDN。這會導致請求變慢,直到內容緩存在 CDN 上。
生存時間 (TTL)確定緩存內容的時間長度。拉取 CDN 可最大限度地減少 CDN 上的存儲空間,但如果文件過期并在文件實際更改之前被拉取,則會產生冗余流量。
流量大的網站可以很好地使用拉式 CDN,因為流量分布更均勻,只有最近請求的內容保留在 CDN 上。
缺點:CDN
- CDN 成本可能很大,具體取決于流量,盡管這應該與不使用 CDN 所產生的額外成本相權衡。
- 如果在 TTL 過期之前更新內容,則內容可能已過時。
- CDN 需要更改靜態內容的 URL 以指向 CDN。
來源和進一步閱讀
- 全球分布式內容交付
- 推式和拉式 CDN 的區別
- 維基百科
負載均衡器
來源(資料來源:可擴展系統設計模式):http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html
負載平衡器將傳入的客戶端請求分發到計算資源,例如應用程序服務器和數據庫。在每種情況下,負載均衡器都會將來自計算資源的響應返回給適當的客戶端。負載均衡器在以下方面有效:
- 防止請求進入不健康的服務器
- 防止資源過載
- 幫助消除單點故障
- 負載均衡器可以使用硬件(昂貴的)或軟件(例如 HAProxy)來實現。
其他好處包括:
SSL 終止- 解密傳入請求并加密服務器響應,因此后端服務器不必執行這些潛在的昂貴操作 無需在每臺服務器上安裝X.509 證書 會話持久性- 如果 Web 應用程序不跟蹤會話,則發出 cookie 并將特定客戶端的請求路由到同一實例 為了防止出現故障,通常設置多個負載均衡器,無論是主動-被動還是主動-主動模式。
負載均衡器可以根據各種指標路由流量,包括:
- 隨機負載
- 最小負載
- 循環或加權循環
- 傳輸層負載
- 應用層負載
負載均衡的缺點:
- 如果負載均衡器沒有足夠的資源或配置不正確,它可能會成為性能瓶頸。
- 引入負載平衡器以幫助消除單點故障會導致復雜性增加。
- 單個負載均衡器是單點故障,配置多個負載均衡器會進一步增加復雜性。
緩存
緩存可以縮短頁面加載時間,并可以減少服務器和數據庫的負載。在這個模型中,調度器會先查找之前是否已經發出過請求,并嘗試找到之前的結果返回,以保存實際執行。
數據庫通常受益于跨其分區的讀取和寫入的均勻分布。熱門商品可能會扭曲分布,導致瓶頸。將緩存放在數據庫前面可以幫助吸收不均勻的負載和流量峰值。
- 客戶端緩存
- CDN緩存
- Web服務器緩存
- 數據庫緩存
- 中間件緩存
緩存缺點
- 一致性問題
- 節點故障帶來延遲
- 額外的開銷和編碼復雜度
異步
異步工作流有助于減少成本高昂的操作的請求時間,否則這些操作將在線執行。他們還可以通過提前完成耗時的工作來提供幫助,例如定期匯總數據。
消息隊列
消息隊列接收、保存和傳遞消息。如果操作太慢而無法內聯執行,您可以使用具有以下工作流程的消息隊列:
- 應用程序將作業發布到隊列,然后通知用戶作業狀態
- 工作人員從隊列中取出作業,對其進行處理,然后發出作業完成的信號
用戶未被阻止,作業在后臺處理。在此期間,客戶端可能會選擇性地進行少量處理,以使任務看起來像是已完成。例如,如果發布一條推文,這條推文可能會立即發布到您的時間線上,但可能需要一些時間才能將您的推文實際發送給您的所有關注者。
Redis作為一個簡單的消息代理很有用,但消息可能會丟失。
RabbitMQ很受歡迎,但需要您適應“AMQP”協議并管理自己的節點。
Amazon SQS是托管的,但可能具有很高的延遲,并且有可能將消息傳遞兩次。
任務隊列
任務隊列接收任務及其相關數據,運行它們,然后傳遞它們的結果。它們可以支持調度,并可用于在后臺運行計算密集型作業。
Celery支持調度,主要支持 python。
背壓
如果隊列開始顯著增長,隊列大小可能會變得大于內存,從而導致緩存未命中、磁盤讀取,甚至性能下降。背壓可以通過限制隊列大小來提供幫助,從而為隊列中的作業保持高吞吐率和良好的響應時間。隊列填滿后,客戶端會收到服務器繁忙或 HTTP 503 狀態代碼,以便稍后重試。客戶端可以稍后重試請求,可能使用指數退避。
缺點:異步
- 廉價計算和實時工作流等用例可能更適合同步操作,因為引入隊列會增加延遲和復雜性。
安全
安全是一個廣泛的話題。除非您有豐富的經驗、安全背景,或者正在申請需要安全知識的職位,否則您可能只需要了解基礎知識:
- 在傳輸和靜止時加密。
- 清理所有用戶輸入或暴露給用戶的任何輸入參數,以防止XSS和SQL 注入。
- 使用參數化查詢來防止 SQL 注入。
- 使用最小權限原則。
以上就是系統設計的大體模塊了,快學習起來吧。