这是一个系统设计的面试问题,要求设计Spotify。在实际面试中,通常会专注于应用的一个或两个主要功能,但在本文中,我想概述一下如何设计这样一个系统,然后如果需要的话,可以深入探讨每个单独的部分。
初始阶段:基础版本需求: 初始要求是处理 500万用户和3000万首歌曲。我们将有播放歌曲的用户和上传歌曲的艺术家。
让我们从估算所需的存储空间开始。首先,我们需要将歌曲存储在某种存储介质中。
- 歌曲存储: Spotify 和类似服务通常使用 Ogg Vorbis 或 AAC 等格式进行流媒体传输,假设平均每首歌的大小为 3MB,那么我们需要 *3MB 3000万 = 90TB** 的存储空间来存储歌曲。
- 歌曲元数据: 我们还需要存储歌曲元数据和用户资料信息。平均每首歌的元数据大小约为 100 字节 — *100 字节 3000万 = 3GB**
- 用户元数据: 平均每名用户我们将存储 1KB 的数据 — *1KB 50万 = 0.5GB**
移动应用: 我们将有一个移动应用,这是用户与服务交互的前端。用户可以搜索歌曲、播放音乐、创建播放列表等。当用户执行某个操作(如播放歌曲)时,应用会向后端服务器发送请求。
负载均衡器: 但在请求到达服务器之前,我们有一个负载均衡器,它会将传入的流量分配到多个Web服务器上。这可以提高我们应用的可用性和容错性。
Web 服务器 (APIs): Web 服务器是处理来自移动应用的请求的 API。例如,如果用户想要播放一首歌曲,请求将发送到这些 Web 服务器。服务器随后确定歌曲的位置(在数据库或存储服务中),并决定如何获取它。
数据存储数据存储将分为两个独立的服务——Blob Storage for Songs,我们将在此存储实际的歌曲文件,以及SQL Database,我们将在此存储歌曲和用户元数据。
歌曲 — Blob 存储(例如,AWS S3、GCP、Azure Blob Storage): 歌曲文件实际存储在 Blob(二进制大对象)存储服务中。这些服务设计用于存储大量非结构化数据。
用户、艺术家和歌曲元数据 — SQL Database: 此 SQL 数据库存储结构化数据,例如用户信息(如用户名、密码和电子邮件地址)和关于歌曲的元数据(如歌曲名称、艺术家名称、专辑详情等)。
为什么使用 SQL?SQL 数据库非常适合这种结构化的数据,因为它们允许执行复杂的查询并建立不同类型数据之间的关系。
每个歌曲文件都存储为一个“blob”,而SQL数据库通常会存储对该文件的引用(如URL)。
SQL 数据库结构这里是我们将在SQL数据库中使用的表及其关系的基本概述:
我们需要一个 Users 表,其中包含用户元数据,如 UserID、Username、Email、PasswordHash、CreatedAt、LastLogin 等。
Songs 表将保存歌曲的元数据信息,例如 SongID(歌曲ID)、Title(标题)、ArtistID(艺人ID)、Duration(时长)、ReleaseDate(发行日期)和 FileURL(文件URL),该 URL 指向存储歌曲文件的位置(例如,在 blob 存储中)。
艺术家表将包含艺术家信息——艺术家ID、姓名、简介、国家等。
关系: 我们将在ArtistsSongs 表中连接 Artists 表和 Songs 表,在那里我们将有 **ArtistID**
(指向 Artists 表的外键)和 **SongID**
(指向 Songs 表的外键)。从那里,我们可以获取歌曲的元数据,该元数据还将包含 **FileURL**
属性,指向歌曲所在的 Blob 存储。
因此,Web 服务器将从 SQL 数据库获取歌曲元数据,然后从歌曲元数据中获取 fileURL
,接着将文件分块从服务器流式传输到移动应用程序。或者,我们也可以直接从对象存储流式传输文件到客户端,绕过 Web 服务器以减少负载。
现在如果我们扩展到5000万用户和2亿首歌曲会怎样?我们首先需要重新计算数据。这意味着SQL数据存储需要存储大约6.66倍的歌曲元数据:
*每首歌100字节 2亿首歌曲 = 20GB**
同样,对于用户元数据也是一样:
*每个用户 1KB 5000万用户 = 50GB**
由于流量增加,我们需要引入缓存和CDN(如Cloudfront / Cloudflare)来提供歌曲,每个CDN都会靠近一个地理区域,因此它可以比Web服务器更快地提供歌曲。
我们可以使用 LRU(最近最少使用)淘汰策略来缓存热门歌曲,而不受欢迎的歌曲仍将从 Blob 存储中获取,然后缓存到 CDN 中。
歌曲文件也可以直接从云存储流式传输到客户端,这将减轻 web 服务器的负载。
数据库扩展:Leader-Follower 技术数据库也需要扩展。因为我们知道我们的应用读取操作远远多于写入操作,意味着有很多用户在听歌,但上传歌曲的艺术家数量相对较少——我们可以使用Leader → Follower 技术,设置一个Leader 数据库来同时接受读取和写入操作,以及多个Follower 或 Slave 数据库,这些数据库只用于读取以获取歌曲和用户元数据。
如果有必要,我们也可以实现数据库分片,将其拆分到多个 SQL 数据库中,或者实现 Leader ↔ Leader 技术,但这些是比较复杂的场景,在面试中不会深入询问这些内容。
如果你想更深入地了解我们在这里讨论的每个组件,我有一个详细的系统设计面试概念教程,在其中我会更详细地讲解每个组件。
如果你是第一次来这里,我是Hayk。我在Web Dev Mastery社区帮助网页开发者获得他们的第一份技术工作或晋升到高级职位。
Web 开发精通掌握必备网页开发技能,获得工作机会,提升职业发展。www.skool.com共同學習,寫下你的評論
評論加載中...
作者其他優質文章