系統設計:設計Spotify
一、初始階段:基礎版本
需求: 初始要求是處理50萬用戶和3000萬首歌曲。我們將有播放歌曲的用戶和上傳歌曲的藝術家。
1.估算:數據計算
讓我們從估算我們需要的存儲開始。首先,我們需要將歌曲存儲在某種存儲中。
- 歌曲存儲: Spotify等服務通常使用Ogg Vorbis或AAC等格式進行流媒體傳輸,假設平均歌曲大小為3MB,我們需要3MB * 3000萬 = 90TB的存儲空間用于歌曲。
- 歌曲元數據: 我們還需要存儲歌曲元數據和用戶配置文件信息。每首歌平均的元數據大小約為100字節 — 100字節 * 3000萬 = 3GB
- 用戶元數據: 平均而言,我們將每個用戶存儲1KB的數據 — 1KB * 50萬 = 0.5GB
2.高級設計
- 移動應用: 我們將有一個移動應用,是用戶與服務互動的前端。用戶可以搜索歌曲,播放音樂,創建播放列表等。當用戶執行操作(如播放歌曲)時,應用程序將發送請求到后端服務器。
- 負載均衡器: 但在到達服務器之前,我們有一個負載均衡器,用于在多個web服務器之間分發傳入流量。這提高了應用程序的可用性和容錯性。
- Web服務器(API): Web服務器是處理移動應用程序發來的請求的API。例如,如果用戶想播放一首歌,請求將發送到這些Web服務器。服務器然后確定歌曲的位置(在數據庫或存儲服務中)以及如何檢索它。
3.數據存儲
數據存儲將分為兩個獨立的服務 — 歌曲的Blob存儲,我們將在其中存儲實際的歌曲文件,以及SQL數據庫,我們將在其中存儲歌曲和用戶元數據。
- 歌曲 — Blob存儲(例如AWS S3、GCP、Azure Blob存儲): 實際的歌曲文件存儲在Blob(二進制大對象)存儲服務中。這些服務設計用于存儲大量非結構化數據。
- 用戶、藝術家和歌曲元數據 — SQL數據庫: 該SQL數據庫存儲結構化數據,如用戶信息(如用戶名、密碼和電子郵件地址)以及關于歌曲的元數據(如歌曲名稱、藝術家名稱、專輯詳細信息等)。
為什么使用SQL?SQL數據庫非常適合這種類型的結構化數據,因為它們允許進行復雜的查詢和不同類型數據之間的關系。
每個歌曲文件都存儲為“blob”,而SQL數據庫通常存儲對此文件的引用(如URL)。
4.SQL數據庫結構
以下是我們SQL數據庫中表及其關系的基本大綱:
我們將需要一個用戶表,其中包含用戶元數據,如UserID、Username、Email、PasswordHash、CreatedAt、LastLogin等。
- 歌曲表將保存歌曲的元數據信息,例如SongID、Title、ArtistID、Duration、ReleaseDate和FileURL,即指向歌曲文件存儲位置的URL(例如在blob存儲中)。
- 藝術家表將包含藝術家信息 — ArtistID、Name、Bio、Country等。
關系: 我們將在藝術家歌曲表中連接藝術家和歌曲表,其中將有**ArtistID**(指向藝術家表的外鍵)和**SongID**(指向歌曲表的外鍵)。從那里,我們可以獲取歌曲元數據,其中還將包含指向歌曲所在的Blob存儲的**FileURL**屬性。
5.將所有內容整合
因此,Web服務器將從SQL數據庫獲取歌曲元數據,從中獲取fileURL,然后將其分塊流式傳輸到移動應用程序?;蛘呶覀兛梢灾苯訌膶ο蟠鎯α魇絺鬏數娇蛻舳耍@過Web服務器以減輕負載。
二、擴展階段:5000萬用戶,2億首歌曲
現在如果我們擴展到5000萬用戶和2億首歌曲呢?我們首先需要重新計算數據。這意味著SQL數據存儲需要存儲200/30 = 約6.66倍的歌曲元數據:
每首歌100字節 * 2億首歌 = 20GB
用戶元數據也是如此:
每個用戶1KB * 5000萬用戶 = 50GB
1.引入CDN
由于流量增加 — 我們需要引入緩存和CDN(如Cloudfront / Cloudflare)來提供歌曲,每個CDN將在地理上接近一個區域;因此,它可以比Web服務器更快地提供歌曲。
我們可以使用LRU(Least Recently Used)淘汰策略緩存熱門歌曲,而不熱門的歌曲仍然將從Blob存儲中獲取,然后緩存在CDN中。
歌曲文件還可以直接從云存儲流式傳輸到客戶端,這將減輕Web服務器的負載。
2.擴展數據庫:領導者-跟隨者技術
數據庫也需要擴展。由于我們知道我們的應用程序獲得的讀取次數比寫入次數多,也就是有很多用戶聽歌曲,但相對較少的藝術家上傳歌曲 — 我們可以使用領導者 → 跟隨者技術,有一個領導者數據庫負責接受讀取和寫入,以及多個跟隨者或從數據庫僅用于檢索歌曲和用戶元數據。
圖片