系統(tǒng)設(shè)計(jì):設(shè)計(jì)Spotify
一、初始階段:基礎(chǔ)版本
需求: 初始要求是處理50萬(wàn)用戶和3000萬(wàn)首歌曲。我們將有播放歌曲的用戶和上傳歌曲的藝術(shù)家。

1.估算:數(shù)據(jù)計(jì)算
讓我們從估算我們需要的存儲(chǔ)開(kāi)始。首先,我們需要將歌曲存儲(chǔ)在某種存儲(chǔ)中。
- 歌曲存儲(chǔ): Spotify等服務(wù)通常使用Ogg Vorbis或AAC等格式進(jìn)行流媒體傳輸,假設(shè)平均歌曲大小為3MB,我們需要3MB * 3000萬(wàn) = 90TB的存儲(chǔ)空間用于歌曲。
- 歌曲元數(shù)據(jù): 我們還需要存儲(chǔ)歌曲元數(shù)據(jù)和用戶配置文件信息。每首歌平均的元數(shù)據(jù)大小約為100字節(jié) — 100字節(jié) * 3000萬(wàn) = 3GB
- 用戶元數(shù)據(jù): 平均而言,我們將每個(gè)用戶存儲(chǔ)1KB的數(shù)據(jù) — 1KB * 50萬(wàn) = 0.5GB

2.高級(jí)設(shè)計(jì)
- 移動(dòng)應(yīng)用: 我們將有一個(gè)移動(dòng)應(yīng)用,是用戶與服務(wù)互動(dòng)的前端。用戶可以搜索歌曲,播放音樂(lè),創(chuàng)建播放列表等。當(dāng)用戶執(zhí)行操作(如播放歌曲)時(shí),應(yīng)用程序?qū)l(fā)送請(qǐng)求到后端服務(wù)器。
- 負(fù)載均衡器: 但在到達(dá)服務(wù)器之前,我們有一個(gè)負(fù)載均衡器,用于在多個(gè)web服務(wù)器之間分發(fā)傳入流量。這提高了應(yīng)用程序的可用性和容錯(cuò)性。

- Web服務(wù)器(API): Web服務(wù)器是處理移動(dòng)應(yīng)用程序發(fā)來(lái)的請(qǐng)求的API。例如,如果用戶想播放一首歌,請(qǐng)求將發(fā)送到這些Web服務(wù)器。服務(wù)器然后確定歌曲的位置(在數(shù)據(jù)庫(kù)或存儲(chǔ)服務(wù)中)以及如何檢索它。
3.數(shù)據(jù)存儲(chǔ)
數(shù)據(jù)存儲(chǔ)將分為兩個(gè)獨(dú)立的服務(wù) — 歌曲的Blob存儲(chǔ),我們將在其中存儲(chǔ)實(shí)際的歌曲文件,以及SQL數(shù)據(jù)庫(kù),我們將在其中存儲(chǔ)歌曲和用戶元數(shù)據(jù)。

- 歌曲 — Blob存儲(chǔ)(例如AWS S3、GCP、Azure Blob存儲(chǔ)): 實(shí)際的歌曲文件存儲(chǔ)在Blob(二進(jìn)制大對(duì)象)存儲(chǔ)服務(wù)中。這些服務(wù)設(shè)計(jì)用于存儲(chǔ)大量非結(jié)構(gòu)化數(shù)據(jù)。
- 用戶、藝術(shù)家和歌曲元數(shù)據(jù) — SQL數(shù)據(jù)庫(kù): 該SQL數(shù)據(jù)庫(kù)存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù),如用戶信息(如用戶名、密碼和電子郵件地址)以及關(guān)于歌曲的元數(shù)據(jù)(如歌曲名稱、藝術(shù)家名稱、專輯詳細(xì)信息等)。
為什么使用SQL?SQL數(shù)據(jù)庫(kù)非常適合這種類型的結(jié)構(gòu)化數(shù)據(jù),因?yàn)樗鼈冊(cè)试S進(jìn)行復(fù)雜的查詢和不同類型數(shù)據(jù)之間的關(guān)系。
每個(gè)歌曲文件都存儲(chǔ)為“blob”,而SQL數(shù)據(jù)庫(kù)通常存儲(chǔ)對(duì)此文件的引用(如URL)。
4.SQL數(shù)據(jù)庫(kù)結(jié)構(gòu)
以下是我們SQL數(shù)據(jù)庫(kù)中表及其關(guān)系的基本大綱:
我們將需要一個(gè)用戶表,其中包含用戶元數(shù)據(jù),如UserID、Username、Email、PasswordHash、CreatedAt、LastLogin等。

- 歌曲表將保存歌曲的元數(shù)據(jù)信息,例如SongID、Title、ArtistID、Duration、ReleaseDate和FileURL,即指向歌曲文件存儲(chǔ)位置的URL(例如在blob存儲(chǔ)中)。
- 藝術(shù)家表將包含藝術(shù)家信息 — ArtistID、Name、Bio、Country等。
關(guān)系: 我們將在藝術(shù)家歌曲表中連接藝術(shù)家和歌曲表,其中將有**ArtistID**(指向藝術(shù)家表的外鍵)和**SongID**(指向歌曲表的外鍵)。從那里,我們可以獲取歌曲元數(shù)據(jù),其中還將包含指向歌曲所在的Blob存儲(chǔ)的**FileURL**屬性。
5.將所有內(nèi)容整合

因此,Web服務(wù)器將從SQL數(shù)據(jù)庫(kù)獲取歌曲元數(shù)據(jù),從中獲取fileURL,然后將其分塊流式傳輸?shù)揭苿?dòng)應(yīng)用程序?;蛘呶覀兛梢灾苯訌膶?duì)象存儲(chǔ)流式傳輸?shù)娇蛻舳耍@過(guò)Web服務(wù)器以減輕負(fù)載。
二、擴(kuò)展階段:5000萬(wàn)用戶,2億首歌曲
現(xiàn)在如果我們擴(kuò)展到5000萬(wàn)用戶和2億首歌曲呢?我們首先需要重新計(jì)算數(shù)據(jù)。這意味著SQL數(shù)據(jù)存儲(chǔ)需要存儲(chǔ)200/30 = 約6.66倍的歌曲元數(shù)據(jù):
每首歌100字節(jié) * 2億首歌 = 20GB
用戶元數(shù)據(jù)也是如此:
每個(gè)用戶1KB * 5000萬(wàn)用戶 = 50GB

1.引入CDN
由于流量增加 — 我們需要引入緩存和CDN(如Cloudfront / Cloudflare)來(lái)提供歌曲,每個(gè)CDN將在地理上接近一個(gè)區(qū)域;因此,它可以比Web服務(wù)器更快地提供歌曲。

我們可以使用LRU(Least Recently Used)淘汰策略緩存熱門(mén)歌曲,而不熱門(mén)的歌曲仍然將從Blob存儲(chǔ)中獲取,然后緩存在CDN中。
歌曲文件還可以直接從云存儲(chǔ)流式傳輸?shù)娇蛻舳?,這將減輕Web服務(wù)器的負(fù)載。
2.擴(kuò)展數(shù)據(jù)庫(kù):領(lǐng)導(dǎo)者-跟隨者技術(shù)
數(shù)據(jù)庫(kù)也需要擴(kuò)展。由于我們知道我們的應(yīng)用程序獲得的讀取次數(shù)比寫(xiě)入次數(shù)多,也就是有很多用戶聽(tīng)歌曲,但相對(duì)較少的藝術(shù)家上傳歌曲 — 我們可以使用領(lǐng)導(dǎo)者 → 跟隨者技術(shù),有一個(gè)領(lǐng)導(dǎo)者數(shù)據(jù)庫(kù)負(fù)責(zé)接受讀取和寫(xiě)入,以及多個(gè)跟隨者或從數(shù)據(jù)庫(kù)僅用于檢索歌曲和用戶元數(shù)據(jù)。
圖片





























