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