自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前端開(kāi)發(fā)者也可以懂的基礎(chǔ) System Design

開(kāi)發(fā) 前端
今天帶來(lái) Kyle Mo 大佬的一篇關(guān)于 System Design 好文,希望對(duì)大家有所幫助,早期成為大神。


大家好,我是小智,今天帶來(lái) Kyle Mo 大佬的一篇關(guān)于 System Design 好文,希望對(duì)大家有所幫助,早期成為大神。PS:文文已經(jīng)過(guò)授權(quán)。

前陣子在與朋友一起籌劃的后端開(kāi)發(fā)線上分享會(huì) BESG 有成員分享了 TinyURL 的系統(tǒng)設(shè)計(jì) (System Design),剛好也看到了知名 YouTuber Terry 關(guān)于 Google 系統(tǒng)設(shè)計(jì)面試的影片,了解到在美國(guó)的資訊業(yè),不論你是前端、后端、資料工程師還是 DevOps,System Design 系統(tǒng)設(shè)計(jì)幾乎都是面試時(shí)的必考題。

有人可能會(huì)覺(jué)得,反正那是國(guó)外的狀況,我在國(guó)內(nèi)找前端的工作,不需要會(huì)系統(tǒng)設(shè)計(jì)也可以錄取吧?是沒(méi)錯(cuò),以目前國(guó)內(nèi)的前端業(yè)界來(lái)看,面試大多是不會(huì)考系統(tǒng)設(shè)計(jì)的,但是其實(shí)學(xué)習(xí)系統(tǒng)設(shè)計(jì)并不僅是為了應(yīng)付面試,更是學(xué)習(xí)如何應(yīng)付復(fù)雜系統(tǒng)的能力,也是從 Junior 開(kāi)發(fā)者過(guò)渡到 Senior 開(kāi)發(fā)者的關(guān)鍵。就算身為前端開(kāi)發(fā)者,也會(huì)需要面對(duì)越來(lái)越復(fù)雜的系統(tǒng),學(xué)會(huì)基本的系統(tǒng)設(shè)計(jì)思維除了能讓你更了解系統(tǒng)的整體架構(gòu)外,同時(shí)也加強(qiáng)在開(kāi)發(fā)時(shí)和其他角色溝通與協(xié)作的能力。

我是一個(gè)剛要進(jìn)入社會(huì),準(zhǔn)備開(kāi)始自己第一份正職的菜鳥(niǎo)工程師,主要 focus 在 Web 前端技術(shù),但也熱衷于學(xué)習(xí)后端開(kāi)發(fā)與云端技術(shù)。我想透過(guò)這篇文章,以自己是前端開(kāi)發(fā)者的角度出發(fā),去介紹我認(rèn)為前端開(kāi)發(fā)者也該擁有的基本系統(tǒng)設(shè)計(jì)思維,也就是說(shuō)主要會(huì)介紹系統(tǒng)設(shè)計(jì)最表層的元素,而不會(huì)去深入探討每一個(gè)技術(shù)的深入實(shí)作,目標(biāo)在廣而不在深。

要知道系統(tǒng)設(shè)計(jì)是一門非常非常非常複雜的技術(shù)(說(shuō)了三次,應(yīng)該了解到底多複雜了??),絕對(duì)不是我這樣的菜雞可以精通的,因此這篇文應(yīng)該會(huì)蠻入門也蠻淺的,主要目的是希望和我一樣剛?cè)胄械那岸碎_(kāi)發(fā)者在看完文章后,也能擁有最基本的系統(tǒng)設(shè)計(jì)思維,除了處理 UI 畫面與瀏覽器相關(guān)的眉眉角角外,應(yīng)該也要理解一個(gè)合格的系統(tǒng)在背后是怎麼運(yùn)作的。

本篇文章的流程會(huì)是這樣的,首先我會(huì)把我認(rèn)為系統(tǒng)設(shè)計(jì)的重要元素列出來(lái),并對(duì)每個(gè)元素進(jìn)行更近一步的介紹,等讀者有了大概的認(rèn)知后,再分享我認(rèn)為在面對(duì)系統(tǒng)設(shè)計(jì)時(shí)可以採(cǎi)用的思維走向,最后再以一個(gè)實(shí)際的系統(tǒng)設(shè)計(jì)范例按照先前介紹的思維走向來(lái)解決問(wèn)題。

以分散式系統(tǒng)為設(shè)計(jì)目標(biāo)

雖然我們知道分散式相對(duì)于單機(jī)來(lái)說(shuō)復(fù)雜許多,在單機(jī)都處理不好的狀況下去碰分散式系統(tǒng)幾乎是死路一條,不過(guò)單機(jī)的 Vertical Scaling 是有侷限性的,并且 Single Point Of Failure 的問(wèn)題也讓系統(tǒng)充滿風(fēng)險(xiǎn),要建立一個(gè)“可靠的大型系統(tǒng)”,採(cǎi)用分散式架構(gòu)似乎是無(wú)法避免了。況且在遇到系統(tǒng)設(shè)計(jì)面試問(wèn)題時(shí),通常都會(huì)預(yù)設(shè)要設(shè)計(jì)的系統(tǒng)是高流量的,畢竟設(shè)計(jì)一個(gè)只能承受低流量的系統(tǒng)是毫無(wú)意義的,因此本篇文章討論的系統(tǒng)設(shè)計(jì)都會(huì)以分散式系統(tǒng)為出發(fā)點(diǎn)。

我們希望設(shè)計(jì)出來(lái)的系統(tǒng)能擁有哪些特性?

Scalability 可擴(kuò)展性

當(dāng)系統(tǒng)遇到的流量漸漸變大時(shí),我們會(huì)希望系統(tǒng)的服務(wù)器或儲(chǔ)存空間也能夠跟著擴(kuò)展,來(lái)避免無(wú)法負(fù)荷的狀況。

用白話一點(diǎn)的方式來(lái)比喻的話,想像今天你跟 4 個(gè)朋友約好要出去玩,你們租了 Toyota 的四人座 Vios,不過(guò)另外 2 個(gè)人看到你們要出去玩,就堅(jiān)持要你們帶上他們,當(dāng)然現(xiàn)在 6 個(gè)人是塞不下小小的 Vios 的,你們只好換租可以載 6 人的 Luxgen U6。

這就很像是系統(tǒng)設(shè)計(jì)垂直擴(kuò)展(Vertical Scaling) 的概念,藉由提升單機(jī) CPU 或內(nèi)存來(lái)提升效能。然而這樣的提升是有限制的,想像越來(lái)越多朋友想跟你們一起出去玩,你說(shuō)到了 30 個(gè)人,你還可以換包游覽車,那 300 個(gè)呢?(別跟我說(shuō)包火車)這時(shí)可能就得放棄全部人都擠一臺(tái)車的方式,改為租用多臺(tái)游覽車來(lái)載運(yùn)所有人。這在系統(tǒng)設(shè)計(jì)上稱作水平擴(kuò)展(Horizontal Scaling),用多臺(tái)機(jī)器來(lái)分流處理單機(jī)可能無(wú)法負(fù)荷的流量,達(dá)到系統(tǒng)的可擴(kuò)展性。

Reliability 可靠性

可靠性代表一個(gè)系統(tǒng)在它開(kāi)始執(zhí)行之后到某個(gè)時(shí)間點(diǎn),系統(tǒng)正常執(zhí)行的機(jī)率,也就是系統(tǒng)無(wú)故障執(zhí)行的概率。

Availability 可用性

可用性是一個(gè)容易跟可靠性搞混的指標(biāo),它的定義為系統(tǒng)在面對(duì)各種異常時(shí)可以正確提供服務(wù)的能力,更嚴(yán)謹(jǐn)?shù)亩x為“系統(tǒng)服務(wù)不中斷運(yùn)行時(shí)間占實(shí)際運(yùn)行時(shí)間的比例?!薄比绻怨絹?lái)看:

Availability % = (available time / total time) *100

因此可用性跟容錯(cuò)性是相關(guān)聯(lián)的,在單機(jī)架構(gòu)下,機(jī)器炸了,使用者也 access 不到服務(wù)了,而分散式的狀況下即使有機(jī)器 shutdown,也會(huì)由其他機(jī)器馬上遞補(bǔ)上,對(duì)用戶來(lái)說(shuō)服務(wù)一直是可用的,這也是為什麼說(shuō)分散式系統(tǒng)可以提升可用性的原因。

Reliability 與 Availability 這兩個(gè)指標(biāo)常常讓人搞混,一個(gè) reliable 的系統(tǒng)通常也會(huì)是一個(gè) available 的系統(tǒng),Availability 雖然可以透過(guò)分散式系統(tǒng)的冗馀電腦 (redundant) 來(lái)達(dá)成,但卻不能保證這個(gè)系統(tǒng)是 reliable 的。

Efficiency 高效率

代表這個(gè)系統(tǒng)的效率如何,一般常見(jiàn)的指標(biāo)有系統(tǒng)的延遲(Latency)與吞吐量(Throughput).

Latency 延遲:執(zhí)行一個(gè)操作要花費(fèi)的“時(shí)間長(zhǎng)度”。以我自己較熟悉的 web 領(lǐng)域來(lái)說(shuō),Latency 指的是使用者發(fā)出請(qǐng)求后,等待 server 接收請(qǐng)求,進(jìn)行處理后回傳給使用者的總花費(fèi)時(shí)間。

Throughput 吞吐量:以一個(gè)時(shí)間區(qū)間作為單位,單位時(shí)間內(nèi)可以執(zhí)行“幾次”操作,或運(yùn)算的“次數(shù)”。同樣以 web 來(lái)舉例,Throughput 指的是單位時(shí)間內(nèi)服務(wù)器可以接收的請(qǐng)求量。

要建構(gòu)一個(gè)高效率的系統(tǒng),我們會(huì)希望系統(tǒng)可以達(dá)到 **Low Latency **與 High Throughput。

Manageability 可管理性

故名思義,代表一個(gè)系統(tǒng)是不是方便管理,是不是能快速迭代新功能?是不是能夠快速追蹤 bug?或是能不能把 infrastructure 抽象化,讓應(yīng)用工程師可以專注在程式邏輯的開(kāi)發(fā)。

System Design Common Components & Topics

無(wú)論是面對(duì)系統(tǒng)設(shè)計(jì)的題目或是自己在思考系統(tǒng)的架構(gòu),有些技術(shù)是建構(gòu)分散式系統(tǒng)時(shí)非常重要的元素,了解這些元素將會(huì)使我們對(duì)于分散式系統(tǒng)更加了解,在系統(tǒng)設(shè)計(jì)時(shí)也更得心應(yīng)手,這些常見(jiàn)的元素有:

Load Balancer Web Server Database (SQL vs NoSQL) Schema Design Caching Replication Partitions Sharding Read/Write Splitting Algorithm Queue Consistent Hashing Proxy CAP Theorem

如果要每個(gè)技術(shù)或概念都介紹的話應(yīng)該得花不少篇幅,因此這邊如果讀者對(duì)某些概念不熟悉,就麻煩自行研究囉!

面對(duì)系統(tǒng)設(shè)計(jì)時(shí)的思維走向

系統(tǒng)設(shè)計(jì)是一個(gè)開(kāi)放式的問(wèn)題,沒(méi)有所謂一定正確且標(biāo)準(zhǔn)的解法,不管哪種方法幾乎都會(huì)帶來(lái) trade off,所以我接下來(lái)提供的思維走向也許不是最好最標(biāo)準(zhǔn)的,也不一定適用于所有的情形,但我認(rèn)為它可以幫助我們快速建構(gòu)出系統(tǒng)的基本雛形與軟硬體需求,如果你對(duì)系統(tǒng)設(shè)計(jì)毫無(wú)想法,不妨試試看參考這個(gè)思維走向,再根據(jù)自己的需求去做細(xì)部的調(diào)整。

Step.1 弄清系統(tǒng)需求

這是最基本卻也是最重要的一步,弄清系統(tǒng)的需求后,你才知道自己到底要設(shè)計(jì)什麼,如果是在系統(tǒng)設(shè)計(jì)的面試,這也是應(yīng)該要盡早跟面試官確定的事。系統(tǒng)需求一般來(lái)說(shuō)可以分為兩種類型:

  • Functional Requirements
  • Non-Functional Requirements

Functional Requirements 代表系統(tǒng)該要有的功能,以 YouTube 系統(tǒng)舉例,使用者可以創(chuàng)建自己的頻道,也可以去訂閱別人的頻道,在訂閱頻道發(fā)布新影片時(shí)會(huì)收到通知…等等你想得到的各種功能,都算在 Functional Requirements 的范疇裡。

Non-Functional Requirements 顧名思義是一些跟系統(tǒng)功能較無(wú)直接關(guān)連的需求,例如系統(tǒng)需要有高可用性、系統(tǒng)延遲需要非常低、需要嚴(yán)格的資料一致性…等等。

Step.2 關(guān)于系統(tǒng)流量、容量、網(wǎng)絡(luò)帶寬等指標(biāo)的粗略計(jì)算

對(duì)系統(tǒng)的流量、儲(chǔ)存空間、網(wǎng)絡(luò)做初步的估算,對(duì)于后面要考慮 scaling、caching、load balancing 時(shí)是有幫助的,再者對(duì)這些指標(biāo)進(jìn)行評(píng)估,也讓我們可以更好的掌握系統(tǒng)的資源成本。

同樣以設(shè)計(jì) YouTube 來(lái)舉例, 我們可以先估算系統(tǒng)大約會(huì)有多少使用者,其中又有多少 DAU (Daily Activated User),估算一天大約會(huì)有幾部影片上傳,影片建立跟讀取的比例是多少…等等,這是比較偏向系統(tǒng)流量的考量。

下一步可以估算系統(tǒng)的儲(chǔ)存容量,例如每年儲(chǔ)存影片的總?cè)萘看蠹s是多少?儲(chǔ)存的資料會(huì)存活多久?如果系統(tǒng)有實(shí)作 Caching,Memory 的用量又大概是多少?

而最后網(wǎng)絡(luò)貸款也是我們可以事先預(yù)估的指標(biāo)。

如果讀者不知道怎麼計(jì)算這些指標(biāo)也不要擔(dān)心,在下一個(gè)章節(jié)會(huì)以設(shè)計(jì) Instagram 為范例跑一次系統(tǒng)設(shè)計(jì)流程,到時(shí)候會(huì)示范估算這些指標(biāo)的方式。

Step.3 定義 System Interface

當(dāng)我們釐清系統(tǒng)的需求后,就可以按照需求來(lái)粗略規(guī)劃系統(tǒng)的 API,這也可以讓我們確認(rèn)先前訂出的系統(tǒng)需求并沒(méi)有定義錯(cuò)誤。這時(shí)可以先思考系統(tǒng)要採(cǎi)用哪種 API 架構(gòu),例如 REST APIs、SOAP、GraphQL,再來(lái)可以簡(jiǎn)單定義出有哪些 API endpoints,以 YouTube 來(lái)舉例:

uploadVideo(user_id, video_content, video_location, user_location, ……) addVideoToFavorite(user_id, video_id, timestamp, …….)

Step.4 定義 Data Model | DB Schema

在 System Design 的前段及早定義出 DB Schema 將幫助我們更清楚系統(tǒng)的資料流,我們應(yīng)該清楚不同 Entities 之間是怎麼互動(dòng)與溝通的,以 YouTube 為例,Data Model 可能是這樣子:

User: UserID, Name, Email, DoB, CreationDate, LastLogin, …. Video: VideoID,VideoLink, VideoLocation, NumberOfLikes, TimeStamp, … .….

在這個(gè)階段也可以先思考究竟系統(tǒng)適合哪種資料庫(kù)?RDBMS 還是 NoSQL ? 還有使用者上傳的影片與圖片,又適合儲(chǔ)存在哪呢?

Step.5 High-level design

這步驟是系統(tǒng)的 High-level 設(shè)計(jì),可以在一張圖表畫出系統(tǒng)大概由哪些 Components 組成,因?yàn)橄惹安襟E已經(jīng)確定了系統(tǒng)需求,也對(duì)流量做了初步估算,所以在這個(gè)步驟我們可以設(shè)計(jì)系統(tǒng)需不需要做分流、讀寫分離,以 YouTube 的例子來(lái)說(shuō),我們可能還需要一個(gè)分散式的檔案儲(chǔ)存系統(tǒng)來(lái)存放影片。

Step.6 System Detailed design

先完成 high-level 的系統(tǒng)設(shè)計(jì),接下來(lái)才進(jìn)入系統(tǒng)的 detailed design,如果是面對(duì)系統(tǒng)面試,在時(shí)間有限的狀況下,可以針對(duì)前面 high-level design 畫出的架構(gòu)圖裡挑出兩三個(gè) components 來(lái)說(shuō)明就好,而這邊建議可以跟著面試官的引導(dǎo)走。(如果不是在面試,當(dāng)然你就有大把時(shí)間可以好好對(duì)每個(gè)環(huán)節(jié)做 detailed 的設(shè)計(jì)了)

針對(duì)特定的 component 或 topic,我們可以提供兩三種可行的方法,并思考它們各自的優(yōu)缺點(diǎn),這也是個(gè)開(kāi)放性的問(wèn)題,重要的是你要能清楚每種方式的 trade off,并找出最“適合”自己系統(tǒng)的做法。

  • 在需要存取大量資料的情況下,我們?cè)撛觞N把資料做 partition 并且存到不同資料庫(kù)伺服器裡 ?
  • 我們應(yīng)該在系統(tǒng)的哪些 layer 加入快取服務(wù) ?
  • 系統(tǒng)中哪些部分比較需要做 load balancing ?

Step.7 找到系統(tǒng)可能瓶頸或 trade off 并嘗試給出解決方案

如果是在系統(tǒng)設(shè)計(jì)的面試中,在做完系統(tǒng)架構(gòu)設(shè)計(jì)之后,可以針對(duì)自己設(shè)計(jì)的系統(tǒng)提出一些可能的瓶頸,畢竟沒(méi)有所謂完美的系統(tǒng)架構(gòu),能夠講出自己所設(shè)計(jì)的系統(tǒng)有哪些缺陷或瓶頸,代表你對(duì)系統(tǒng)整體的掌握度是高的,也許在面試官的眼中是加分的行為(不過(guò)這邊可能得注意挖坑給自己跳的狀況)。

嘗試設(shè)計(jì)一個(gè) Instagram 吧!

雖然知道了面對(duì)系統(tǒng)設(shè)計(jì)可以採(cǎi)取的思路,但我相信各位讀者看到這裡還是覺(jué)得十分抽象吧?那不如我們就按照前面的思考步驟實(shí)際設(shè)計(jì)一個(gè) IG 系統(tǒng)體會(huì)看看吧!(下面代稱這個(gè)系統(tǒng)為“Fake IG”好了??)

(大家應(yīng)該都知道 IG 是什麼吧!???)

Step.1 理清系統(tǒng)需求

前面有提到可以針對(duì)“Functional Requirements”與 “Non-Functional Requirements”來(lái)區(qū)分系統(tǒng)需求

Functional Requirements:

  • 使用者可以上傳照片、影片,另外也可以讀取與下載
  • 使用者可以追蹤其他使用者以觀看最新貼文
  • 使用者可以根據(jù) tags 來(lái)搜尋文章
  • 當(dāng)使用者刷新頁(yè)面后,系統(tǒng)會(huì)根據(jù)使用者追蹤的人顯示該些用戶的最新貼文

Non-Functional Requirements:

  • Fake IG 系統(tǒng)需要具有高可用性(high availability)
  • 刷新頁(yè)面看最新貼文時(shí)可以允許短暫的延遲
  • 在某些狀況下,系統(tǒng)的一致性可以犧牲,例如使用者貼文的愛(ài)心數(shù)量(每個(gè)使用者看到的數(shù)量即使不一樣,也不會(huì)造成什麼影響)
  • 系統(tǒng)希望可以擁有高可靠性(high reliability),使用者上傳的照片、影片不能夠遺失

我們都知道實(shí)際上 IG 的功能絕對(duì)比上面列出來(lái)的還要多,例如在照片上標(biāo)記其他使用者、限時(shí)動(dòng)態(tài)…等等,這些較進(jìn)階的功能可以自己思考要不要列出。(設(shè)計(jì)出基本功能比較重要)

Step.2 關(guān)于系統(tǒng)流量、容量、網(wǎng)絡(luò)帶寬等指標(biāo)的粗略計(jì)算

關(guān)于系統(tǒng)的流量,我們可以先假設(shè)高一點(diǎn),畢竟設(shè)計(jì)能面對(duì)高流量的系統(tǒng)才有意思。假設(shè)我們的 Fake IG 系統(tǒng)的使用者總?cè)藬?shù)有 5000 萬(wàn)人,當(dāng)然裡面不乏許多早就沒(méi)在使用的幽靈用戶,所以這邊假設(shè)每天仍然活躍的用戶(daily active users, DAU)有 100 萬(wàn)人。

接下來(lái)我們先忽略使用者可以上傳影片這個(gè)行為,先限定使用者只能夠上傳照片,不然要考慮的因素實(shí)在太多了。假設(shè)一天大約有 150 萬(wàn)張照片會(huì)被上傳,平均一張照片的檔案大小為 250 KB,那麼儲(chǔ)存一天中新上傳的照片總共需要的容量為

1.5M * 250KB ~= 375GB

如果將時(shí)間拉遠(yuǎn)來(lái)看,10 年下來(lái)存放照片需要的容量為

375GB * 365(days) * 10 ~= 1368.75TB

當(dāng)你在后面的步驟定義好 DB Schema 后,也可以再回過(guò)頭來(lái)用同樣的方式估算資料庫(kù)要儲(chǔ)存的資料總大小,例如我們的系統(tǒng)一定會(huì)有儲(chǔ)存用戶資訊的 User Table ,而它的欄位與空間如下

UserID (4 bytes) + Name (20 bytes) + Email (32 bytes) + Birthday (4 bytes) + CreationDate (4 bytes) = 64 bytes

先前有假設(shè) Fake IG 的使用者總?cè)藬?shù)有 5000 萬(wàn)人,因此儲(chǔ)存用戶資訊的 total storage 約為:

50M 64 ~=3.2GB*

其他的 DB Schema 與上傳圖片使用的 Network Bandwidth 也可以採(cǎi)用類似的方法估算需要的容量。

Step.3 定義 System Interface

規(guī)劃系統(tǒng) API 的步驟,因?yàn)槭且粋€(gè)十分開(kāi)放式的問(wèn)題,答案也不太會(huì)影響接下來(lái)的步驟因此這邊就不多花篇幅說(shuō)明。

Step.4 定義 Data Model | DB Schema

定義出 Data Model 可以讓我們清楚數(shù)據(jù)的關(guān)聯(lián)與數(shù)據(jù)的流動(dòng),在未來(lái)要做 data sharding 或 partitioning 時(shí)也會(huì)比較容易。在 Fake IG 系統(tǒng)中,我們先假設(shè)只需要先考慮使用者與用戶上傳的照片就好(不然我這邊會(huì)寫不完,還請(qǐng)高抬貴手),在學(xué)生時(shí)期十分認(rèn)真修資料庫(kù)課程的你可能會(huì)馬上畫出以下的數(shù)據(jù)庫(kù)關(guān)聯(lián)圖

畫完圖后你可能會(huì)覺(jué)得這個(gè) use case 還蠻適合使用如 MySQL 的 RDBMS 的,畢竟數(shù)據(jù)是有 join 的需求的。不過(guò) RDBMS 在 Scaling 上是非常非常複雜且困難的,例如數(shù)據(jù)一致性的處理方式也與單機(jī)時(shí)大不相同。而使用 NoSQL 其實(shí)也是可行的,雖然可能需要一些額外的 table 來(lái)儲(chǔ)存數(shù)據(jù)的關(guān)聯(lián) (例如 UserPhoto),不過(guò)在 Scaling 上卻較為簡(jiǎn)單。我也沒(méi)辦法告訴你,使用 RDBMS 還是 NoSQL 好,它們各有各的優(yōu)缺點(diǎn)也有各自適用的時(shí)機(jī),因此這個(gè)問(wèn)題也算是開(kāi)放式的,應(yīng)該在多深入了解后再做出選擇。

另外像照片影片這種資源,一般會(huì)需要像是 AWS S3 這樣的 Distributed File Storage,而在我們的數(shù)據(jù)庫(kù)中則只存圖片或影片在 file storage 的 link 還有其他的 meatdata。

Step.5 High-level design

當(dāng)然我們也不一定要畫出整個(gè)系統(tǒng)的架構(gòu)圖,尤其是在面試的話,我們得在有限的時(shí)間內(nèi)盡量 focus 在系統(tǒng)的重點(diǎn)部分,以 Fake IG 來(lái)說(shuō)我們先試著設(shè)計(jì)使用者上傳照片與讀取照片的功能。

以 high-level 的角度來(lái)看 Fake IG 的照片系統(tǒng),大致上會(huì)有兩種情境,也就是用戶上傳照片與讀取照片,所以我們會(huì)需要一臺(tái) application server 來(lái)處理使用者的讀寫 requests,另外會(huì)需要一個(gè)如 AWS S3 一樣的分散式 file Storage 來(lái)儲(chǔ)存照片,另外也會(huì)再開(kāi)一個(gè) database 來(lái)儲(chǔ)存照片相關(guān)的 metadata。

Step.6 System Detailed design

不過(guò)仔細(xì)思考就會(huì)知道上傳照片相比讀取照片所耗費(fèi)的時(shí)間會(huì)多出更多,因?yàn)樯蟼髡掌赡苌婕傲擞脖P的寫入,也不像讀取一樣可以加一層快照層。通常 web server 是有連線數(shù)量的限制的,如果上傳照片的過(guò)程太耗時(shí),可能會(huì)占用 web server 的連線請(qǐng)求,導(dǎo)致要讀取照片的 request 被卡住,造成響應(yīng)的延遲。要處理這個(gè) bottleneck 的其中一種方式就是將讀取與上傳拆成兩個(gè)獨(dú)立的 server 來(lái)分別處理請(qǐng)求,而負(fù)責(zé)上傳照片的 server 還能搭配 message queue 來(lái)消化請(qǐng)求。這樣的做法還有一個(gè)好處就是兩個(gè)服務(wù)可以依照需求各自 Scale 與 Opimize。

對(duì)于 Availability 與 Reliability,也可以考慮為系統(tǒng)的各個(gè) component 加入 replica service,這樣 horizontal scaling 的結(jié)果是可以避免 single point of failure,在其中一個(gè)服務(wù)節(jié)點(diǎn)掛掉時(shí)仍能保持系統(tǒng)可用性,搭配 Load Balancer 也可以做到流量的分流,降低系統(tǒng)的延遲。

提到 Load Balancer,它的目的是達(dá)成 horizontal scaling,不過(guò)它也可能會(huì)有 single point of failure 的風(fēng)險(xiǎn),因此 replica 也可以應(yīng)用在它上面。就算是只需要一個(gè) instance 來(lái)運(yùn)作的服務(wù),也可以為其建立 redundant secondary copy,這個(gè) copy 不會(huì) serve 任何的流量,卻可以當(dāng)作備胎,在主服務(wù)掛掉時(shí)立即取代它的工作成為 master node。

同樣的 Scaling 思維也適用于儲(chǔ)存服務(wù)例如 Fake IG 使用的 File Storage 與 Database,畢竟我們不希望系統(tǒng)出現(xiàn)檔案或資料遺失的狀況,因此可以為 Database 與 File Storage 加 backup server,讓數(shù)據(jù)也可以避免單點(diǎn)失效后遺失的問(wèn)題。

不過(guò)還是得呼吁一下,加 replica services 未必能改善所有性能或其他的瓶頸,再來(lái)成本也是需要考量的一個(gè)元素,因此還是得依照需求謹(jǐn)慎評(píng)估是否需要 scaling,需要的話也要謹(jǐn)慎評(píng)估 scaling 的程度。

更進(jìn)一步可以思考 database 數(shù)據(jù)是不是需要 Partitioning 或 Sharding,前者是在同一個(gè)數(shù)據(jù)庫(kù)中將 table 拆成數(shù)個(gè)小 table,后者則是將 table 放到數(shù)個(gè)數(shù)據(jù)庫(kù)中。

Partitioning 的 table 與 schema 可能會(huì)改變,Sharding 的 schema 則是相同,但分散在不同數(shù)據(jù)庫(kù)中,Partitioning 是為了分散單表的壓力,Sharding 則是分散單庫(kù)的壓力,實(shí)際上還是要依照需求找出適合當(dāng)前系統(tǒng)的方式。

以 Fake IG 來(lái)說(shuō),如果真要選擇我可能會(huì)選擇比較容易擴(kuò)展的 Sharding,不過(guò) Sharding 也帶來(lái)相當(dāng)多的問(wèn)題例如橫跨不同 shards 的 transaction、rollback、schema change、join、每個(gè) shard db 還要另外去做 backup……等等。

如果選擇了 Sharding 的方式,那麼 Shard 時(shí)依賴的 key 就很重要了,一般來(lái)說(shuō)可以分為 Range-based 與 Hash 兩種方式(如果完全不知道 Sharding 的讀者可以參考我之前的筆記文章),假設(shè)我們以 userId 來(lái)作為 shard 的 key,那可能會(huì)出現(xiàn) hot user 造成某一個(gè)數(shù)據(jù)庫(kù) loading 過(guò)重的問(wèn)題(想想那些在 IG 上追蹤人數(shù)破億的全球巨星,一天不知道會(huì)有多少使用者去瀏覽他們的文章呢,那麼存取這些明星數(shù)據(jù)的數(shù)據(jù)庫(kù)可能流量就會(huì)比其他 instance 還要大很多)。

總之我覺(jué)得 Sharding 的複雜度還有坑真的是挺多的,也許在一開(kāi)始得先考慮清楚系統(tǒng)是不是真的需要 Sharding,如果在面試提出要做 Sharding 或 Partitioning,也要做好萬(wàn)全準(zhǔn)備,以免只是挖更多坑給自己跳。

當(dāng)然 Caching 也是一個(gè)必定要考慮的機(jī)制,因?yàn)?Fake IG 會(huì)產(chǎn)生許多圖片,而這些資源非常適合暫存在離 end users 更接近的 CDN 裡。除了 CDN Cache,也可以在數(shù)據(jù)庫(kù)前加一個(gè)例如 Memcache 的快照服務(wù)器,用來(lái)暫存一些較常被抓取的資料。

關(guān)于到底要存哪些數(shù)據(jù)到快照這個(gè)問(wèn)題,我們不可能把所數(shù)據(jù)都放到快照裡,根據(jù)“80–20 Rule”,80% 的流量可能都來(lái)自于 20% 的 hot data,因此我們可以找出較常被 user 存取的 20% photo 與 metadata 數(shù)據(jù)存到緩存中。

而快照是需要一些清除策略(cache eviction policy)的,不然無(wú)限增長(zhǎng)的狀況下很容易就沒(méi)有快照空間了。在 Fake IG 系統(tǒng)中,我覺(jué)得 LRU Cache (Least Recently Used Cache)就還蠻適合的,當(dāng)要清除快取空間時(shí),可以先從近期最少被存取的數(shù)據(jù)開(kāi)始移除。

總結(jié)

雖然說(shuō)身為前端開(kāi)發(fā)者,在求職過(guò)程甚至是整個(gè)職涯都有可能不會(huì)碰到系統(tǒng)設(shè)計(jì)相關(guān)的問(wèn)題,不過(guò)因?yàn)槲覍⒆约憾x為雜食性的軟體工程師,遇到有興趣、有挑戰(zhàn)性的技術(shù)我都想學(xué),再加上自己一直有個(gè)不切實(shí)際的硅谷夢(mèng),所以依然深信自己未來(lái)某一天也會(huì)遇到系統(tǒng)設(shè)計(jì)的挑戰(zhàn)。而自己也的確在接觸這些內(nèi)容后對(duì)整個(gè)系統(tǒng)應(yīng)用架構(gòu)有了更進(jìn)一步的了解,所以我非常推薦前端開(kāi)發(fā)者也可以嘗試了解最基礎(chǔ)的系統(tǒng)設(shè)計(jì)。

作者:HannahLin 來(lái)源:medium

原文:https://medium.com/starbugs/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC%E8%80%85%E4%B9%9F%E5%8F%AF%E4%BB%A5%E6%87%82%E7%9A%84%E5%9F%BA%E7%A4%8E-system-design-5468e0f43033

責(zé)任編輯:姜華 來(lái)源: 大遷世界
相關(guān)推薦

2018-10-29 10:08:01

2019-03-12 10:38:18

前端開(kāi)發(fā)Nginx

2015-11-24 09:17:01

產(chǎn)品設(shè)計(jì)UI

2017-01-16 13:15:19

前端開(kāi)發(fā)者清單

2014-08-07 10:13:43

谷歌Material De設(shè)計(jì)規(guī)范

2012-08-14 17:14:50

瀏覽器IE6

2021-04-08 10:40:24

前端工具代碼

2012-06-13 01:23:30

開(kāi)發(fā)者程序員

2021-04-01 07:52:57

前端開(kāi)發(fā)技術(shù)熱點(diǎn)

2013-03-11 14:54:03

硅谷移動(dòng)開(kāi)發(fā)者推廣

2018-01-08 10:39:17

前端技術(shù)框架

2015-03-10 09:23:21

前端開(kāi)發(fā)Sublime插件Sublime

2013-10-08 10:42:27

前端開(kāi)發(fā)開(kāi)發(fā)

2013-08-08 10:26:08

前端開(kāi)發(fā)Web

2017-06-26 15:32:59

前端編譯原理語(yǔ)言知識(shí)

2015-07-29 09:53:57

前端開(kāi)發(fā)總結(jié)

2021-12-15 20:06:48

ReactJSSentry開(kāi)發(fā)者

2011-12-01 15:48:13

Web

2023-12-04 07:06:11

2019-07-18 10:14:32

前端Javascript圖表庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)