网易云音乐的评论回帖是怎么存的?

网易云音乐的评论回帖是怎么存的?关系性数据库还是给非关系性数据库,又或者是两者同时使用?一首歌的回帖就30多万了,感觉用关系性数据库的话,效率很低?求大神解答

图片描述

阅读 5.7k
2 个回答

效率低? MySQL 毕竟是个久经考验的数据库,它没你想得那么脆弱。

再一个,讨论问题要考虑场景:

  1. 是不是所有歌曲都有几十万的评论量?
  2. 网易云音乐歌曲的 评论 看起来只有 赞数 这个字段会在记录生成后被修改,这意味着大多数时间它都是只读的,因此对于热门评论可以做热缓放在前面抗压。
  3. 并不是一次性拉取几十万条评论到客户端,如前面所说,热评可以放热缓分压,客户端方面即使拉取不那么热的评论,也可以一次十条/百条去拉。
  4. 其实这种大量只读的情况下,热缓做得好,命中率高的话,数据库方面本身就不会承受特别多的压力。

以上仅是个人想法,有错误还请指正 :)

仅从MongoDB的角度说明这种东西可以怎么存。至于别人到底是怎么存,我们是不知道的。

关系模型存法

不多介绍,可以按照范式设计成跟关系数据库一样的表结构来存储,大概是:

{
    _id: ObjectId(...),
    comment: "...",
    time: ISODate(...),
    user: "...",
    musicId: "...",
    ...
}

如果用惯关系数据库的用户,这样的做法简单自然。在现在讨论的场景下,这样没有太大的问题,在数据量大时可以使用分片来达到水平扩展以应对数据量的增长。
不过仍有可以改进的地方。这要从MongoDB的模型设计来讲起。简单地说,MongoDB是实用主义,怎么方便怎么来,怎么快怎么来,完全不应该受范式的约束。但这也意味着你的模型要从应用的需求出发。仅从上面截图的信息,可能有2个不同的需求:

  1. 评论
  2. 点赞

考虑到评论和点赞都有可能上万甚至上十万百万,它们以单独的集合来存放会比较合适。但是为了读取和存储效率,我会考虑把多条评论压缩到一起,这种方式通常称为分桶(bucket)。

非关系模型存法

{
    _id: ObjectId(...),
    musicId: "...",
    // 根据需要可能将音乐本身的一些数据冗余进来
    musicName: "...",
    comments: [
        {content: "...", time: ISODate(...), user: "..."},
        {content: "...", time: ISODate(...), user: "..."},
        {content: "...", time: ISODate(...), user: "..."},
        ...
    ],
    count: 10, // 该桶内已有10条comments
}

comments的数据量我会考虑一页会展示多少评论(比如30条),那么在添加评论时可以有:

db.comments.updateOne({
    musicId: "...",
    count: {$lt: 30}
}, {
    $push: {
        comments: {content: "...", time: ISODate(...), user: "..."}
    },
    $inc: { count: 1 }
}, {
    upsert: true
});
// 优化查询速度会使用到索引:
db.comments.createIndex({
    musicId: 1,
    count: 1
});

在查询时总是只需要最多取最新的2条记录就可以查到第一页:

db.comments.find({
    musicId: "..."
}).sort({_id: -1}).limit(2)
// 这个查询需要索引
db.comments.createIndex({
    musicId: 1,
    _id: -1
});

注意_id的高4位是时间,所以是可以排序的,其顺序就是时间顺序。
点赞的问题可以通过类似的方式实现,就留给你自己思考了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题