Design a new service for users to create playlists and store songs in them.
Functional requirements
- Users can create any number of playlists.
- Users can add songs to a playlist.
- Another team has already created some self-hosted playlists.
- Support 3 types of playlists:
- platform-created playlists
- user-created playlists
- personalized playlists generated based on user preferences
Questions
- Do we have a limit on the number of playlists or number of songs per playlist?
- Do we need to support things like downloading songs within a playlist, or is just tracking the playlist content enough?
Non-functional requirements
Capacity estimation question:
1. What is the expected number of write (change playlist) and read (view playlist) requests per second?
80 million daily active users. Assume each user makes on average 1 write request per day. Then we have about 8 × 10^7 requests per day. Divide by around 10^5 seconds per day, and we have around thousands of write requests per day.
I think the system is read-heavy, so we might have tens of thousands of read requests.
2. How long do we need to persist playlist setup for, like forever?
So the non-functional requirements can be:
- Scalability: Must support millions of users, each with potentially hundreds of playlists.
- Only allow up to 1000 items per playlist.
- Low latency: Read operations (get playlist, list songs) should be fast (<100ms).
- Since this is a read-heavy system, I would say eventual consistency is enough. In terms of CAP theorem, we would prefer availability over consistency. For example, if a user modifies a playlist by adding a new song, the iPad or computer on the same account might get some delay, like the song is updated after a second or something, so not immediately consistent but will sync eventually.
API design
1. API to create a new playlist
POST /api/v1/playlists
Body:
{"name": "some playlist name", "type": "USER_CREATED"}
2. API to add a new song to a playlist
POST /api/v1/playlists/{playlist_id}/songs
Body:
{"song_id": "SONG_001"}
3. API to delete a playlist or delete a song from a playlist
DELETE /api/v1/playlists/{playlist_id}/songs/{song_id}
DELETE /api/v1/playlists/{playlist_id}
4. Get all playlists of a customer
GET /api/v1/playlists?user_id=123
5. Get playlist content
GET /api/v1/playlists?playlist_id=123
6. Get a specific song
GET /api/v1/playlists/{playlist_id}/songs/{song_id}
To save time, let’s do the high-level design. I will talk about the data schema later.
这道题是一个典型的播放列表系统设计题,核心是围绕“写少读多”的业务特点来做架构取舍:写请求包括新建歌单、增删歌曲,读请求包括查看歌单和播放下一首,因此需要把读路径做得很快,同时接受最终一致性。高层上可以把写流量打到 Playlist Management Service 和数据库,把读流量走独立的 Playlist Read Service,并配合 Redis 缓存来降低延迟;写入后通过队列或 CDC 异步刷新缓存,避免读写互相阻塞。由于每个 playlist 最多 1000 首歌,且用户规模可达数千万,数据存储上适合按 user_id / playlist_id 分区,并将歌曲元数据和实际音频文件解耦,音频文件放在对象存储 /CDN 中以支持快速分发。