SWE · System Design

Meta 个人音乐TopK:评分口径、预计算与首次读取

设计用户音乐品味榜,区分统计最常听与推荐未来偏好,处理首次读取。

题目重点:设计用户音乐品味榜,区分统计最常听与推荐未来偏好,处理首次读取。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练接口返回该用户最近窗口内偏好最高的歌曲/艺人TopK;评分可先选有效播放次数或时长,窗口、skip、重复与tie需明确。它不是全站热榜。
  • “第一次读取榜单”不等于“新用户无历史”;一个老用户第一次请求仍可能有大量listen事件。推荐与已听统计是两种产品合同,以下先实现统计榜。

解题路线

  1. 播放事件带eventId/user/item/session/sequence、有效播放时长与eventTime;session增量或最终汇总只选一致口径,避免每个heartbeat累计完整时长翻倍。
  2. 按user/timeBucket/item聚合有效贡献,dedup事件并对skip/退订删除等政策处理。窗口移出需减贡献,不能只累加累计总榜。score及tie如(-score,itemId)固定,查询返回asOf/window。
  3. 活跃用户异步维护TopK读模型,cache按user/windowVersion隔离。第一次读没有cache时,从已有聚合计算并缓存,而非扫描无限原始历史;singleflight避免同用户并发首次读重复重算。
  4. 真正新用户无播放时,返回空统计榜或明确标注的推荐fallback。若冷启动热门/兴趣选择要做推荐,则不能伪装成“你的已听TopK”。
  5. 更新读取可有界延迟,缓存和聚合version一致;先写事实再发布读模型,late事件修正历史bucket,超保留范围重算或拒绝需明确。用户删除历史时同步失效榜单,不能缓存私人音乐历史供他人读取。

手动走一遍

用户已有1000次播放但榜单cache从未创建,首次读应对预聚合item scores取TopK;无播放新用户才是空榜。听歌10分钟每分钟上报累计1…10分钟,直接sum会计55分钟,需累计差分或最终事件。

规模与取舍

U用户、用户I个有效item,查询全排序O(I log I),小K heap O(I log K),预计算查询O(K)。在线维护动态TopK需处理窗口减少和候选回补,不是只用保存K项的minheap就精确覆盖所有更新。

易错点与追问

容易失分的边界

  • 第一次请求就返回全球热门,混淆有历史cache miss与无历史cold start。
  • 每次heartbeat重复算累计时长,偏好分数严重偏大。

继续深挖

  • 歌曲与艺人榜如何共享事实但避免合作艺人贡献重复?
  • 若改推荐TopK,离线评估与曝光反馈怎样区别已听统计准确性?
✓已复制微信号!