【系统设计】面试问题:设计 Spotify
@TOC
推荐超级课程:
这是一道系统设计面试题,就是设计Spotify。在真正的面试中,通常,您会关注应用程序的一两个主要功能,但在本文中,我想对如何设计这样的系统进行高级概述,然后您可以更深入地研究如果需要的话,可以将其分为每个单独的部分。
初始阶段:基础版本
**要求:最初的要求是处理50 万用户和 30M 首歌曲。**我们将有播放歌曲的用户和上传歌曲的艺术家。
估计:数据数学
让我们首先估计我们需要的存储空间。首先,我们需要将歌曲存储在某种存储中。
- 歌曲存储: Spotify 和类似服务通常使用 Ogg Vorbis 或 AAC 等格式进行流式传输,假设平均歌曲大小为 3MB,则我们需要3MB * 3000 万 = 90TB的歌曲存储空间。
- **歌曲元数据:**我们还需要存储歌曲元数据和用户个人资料信息。每首歌曲的平均元数据大小约为 100 字节 — 100 字节 * 3000 万 = 3GB
- **用户元数据:**平均而言,我们将为每个用户存储 1KB 的数据 — 1KB * 500,000 = 0.5GB
高层设计
**移动应用程序:**我们将有一个移动应用程序,它是用户与服务交互的前端。用户可以搜索歌曲、播放音乐、创建播放列表等。当用户执行操作(例如播放歌曲)时,应用程序会向后端服务器发送请求。
**负载均衡器:**但在到达服务器之前,我们有一个负载均衡器,它将传入流量分配到多个 Web 服务器上。这提高了我们的应用程序可用性和容错能力。
Web 服务器 (API): Web 服务器是处理来自移动应用程序的传入请求的 API。例如,如果用户想要播放歌曲,请求就会发送到这些网络服务器。然后,服务器确定歌曲所在的位置(在数据库或存储服务中)以及如何检索它。
数据存储
数据存储将分为两个独立的服务 -歌曲的 Blob 存储(我们将在其中存储实际的歌曲文件)和SQL 数据库(我们将在其中存储歌曲和用户元数据)。
**歌曲 - Blob 存储(例如,AWS S3、GCP、Azure Blob 存储):**实际的歌曲文件存储在 Blob(二进制大型对象)存储服务中。这些服务旨在存储大量非结构化数据。
**用户、艺术家和歌曲元数据 — SQL 数据库:**此 SQL 数据库存储结构化数据,例如用户信息(如用户名、密码和电子邮件地址)和歌曲元数据(如歌曲名称、艺术家姓名、专辑详细信息等)。
为什么是 SQL?SQL 数据库非常适合此类结构化数据,因为它们允许复杂的查询以及不同类型数据之间的关系。
每个歌曲文件都存储为“blob”,SQL 数据库通常会存储对此文件的引用(如 URL)
SQL数据库结构
以下是 SQL 数据库中的表及其关系的基本概述:
我们需要一个包含用户元数据的用户表,如用户 ID、用户名、电子邮件、密码哈希、CreatedAt、LastLogin 等。
歌曲表将保存歌曲元数据信息,例如歌曲 ID、标题、艺术家 ID、持续时间、发行日期和文件 URL,文件 URL 是歌曲文件存储位置(例如,在 Blob 存储中)的 URL。
艺术家表将包含艺术家信息——艺术家 ID、姓名、简介、国家/地区等。
关系:我们将在****ArtistsSongs Table中加入 Artists 和 Songs 表,其中我们将有**ArtistID**
(指向 Artists 表的外键)和**SongID**
(指向 Songs 表的外键)。从那里,我们可以获得歌曲元数据,其中还将包含**FileURL**
指向歌曲所在Blob 存储的属性。
把它们放在一起
因此,Web 服务器将从 SQL 数据库获取歌曲元数据,并从歌曲元数据获取 ,fileURL
然后将其从服务器逐块流式传输到移动应用程序。或者我们可以直接将它们从对象存储传输到客户端,绕过网络服务器以减少负载。
规模化阶段:5000 万用户、2 亿首歌曲
现在,如果我们扩展到 5000 万用户和 2 亿首歌曲怎么办?我们首先需要重新计算数据。这意味着 SQL 数据存储需要存储 200/30 = ~6.66 倍的歌曲元数据:
每首歌曲 100 字节 * 2 亿首歌曲 = 20GB
用户元数据也是如此:
每个用户 1KB * 5000 万用户 = 50GB
引入 CDN
由于流量增加 - 我们需要引入缓存和 CDN(如 Cloudfront / Cloudflare)来提供歌曲,并且每个 CDN 在地理位置上都将靠近一个区域;因此,它可以比网络服务器更快地提供歌曲。
我们可以使用LRU(最近最少使用)驱逐策略来缓存流行歌曲,不流行的歌曲仍然会从Blob存储中获取,然后缓存到CDN。
歌曲文件还可以直接从云存储传输到客户端,这将减少网络服务器的负载。
扩展数据库:领导者-跟随者技术
数据库也需要扩展。由于我们知道我们的应用程序的读取次数多于写入次数,这意味着有很多用户在听歌曲,但上传歌曲的艺术家数量相对较少 - 我们可以使用 Leader → Follower 技术,并拥有一个可以接受的Leader 数据库读/写和多个追随者或从属数据库将是只读的,用于检索歌曲和用户元数据。
如果有必要,我们还可以实现数据库分片,将其拆分为多个 SQL 数据库,或者实现 Leader ↔ Leader 技术,但这些都是更复杂的场景,并且你不会遇到对此问题问得太深的面试。