点赞功能实现思路阅读 | 青训营笔记

573 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天。

本文以 CC-BY-SA 4.0 发布。

点赞系统

基本上所有社交网络平台上都会有点赞系统的存在,微博、朋友圈、掘金、抖音莫不如此。 当然,不同平台的点赞对应的功能有一些差别。 汇总一下,一个点赞系统的需要提供的功能大致如下:

  1. 某一用户个人的点赞记录
  2. 某一对象被点赞的计数
  3. 某一对象被点赞的具体记录

在数据量较大时,从对象被点赞的具体记录中(例如通过 SELECT COUNT(*) ...) 来汇总得出点赞的计数开销较大,因此点赞系统通常被分为点赞具体记录以及计数系统两部分。

计数系统

计数系统和点赞系统的其它部分是相对独立的。 评论计数、发文计数、关注计数等等都可以独立出一个共用的计数系统来使用。

[WeiDesign]微博计数器的设计(下) · Cydu's Blog 这篇文章基于微博级别的数据量及并发给出了非常详细的论述。 文章里从简单到复杂大概分为三种思路:

  1. 关系数据库:
    • 最开始可以直接 UPDATE ... SET count = count + 1
    • 数据量上来了可以用 Redis 等缓存;
    • 缺点:数据量到了微博数量级后分库分表麻烦,高并发也有缓存失效问题。
  2. 纯 Redis:
    • 缺点:内存开销大,一个字“贵”。
  3. 自己写一个类 Redis 的计数专用数据系统实现:
    • 这就不是我等凡人能触及的领域了。

总之,如果没有到微博数量级的数据量和并发的话, 大概 RDBMS + 多级缓存 + 一定程度的操作合并就已经能够满足大多数需求了。

计数系统还可以提的一点是不要用 Cassandra 的 counter 来实现,详情可以看 Cassandra counter columns: Nice in theory, hazardous in practice。 总而言之是开销极大。

点赞具体记录

这部分内容记录了用户点赞过什么以及点赞了某一对象(如某条微博)的人。 一般来说,用户会希望有一个记录了自己点赞记录的列表, 但是反过来的话,某一对象的点赞列表不是所有平台都支持。 (例如掘金,你看不到一篇文章具体是谁点赞的,只有作者会收到通知。 掘金这部分更多是通知系统负责,而不是点赞系统。)

两个需求:

  • (一般必须)用户的点赞记录
  • (可能不需要)某一条微博的点赞人列表

这两个需求说到底就是一个索引还是两个索引的问题。 一个索引的话,用 RDBMS 的话来说,直接用主键索引即可,不需要多余的索引, 写入性能会有提升,也能省点储存空间。

此外,如果用的不是 RDBMS 而是 NoSQL 的话(如 Redis),一个索引哈系表轻轻松松, 但是两个索引的话就会需要考虑原子操作了(如 Redis 的 Lua 脚本)。

这方面的文章掘金上和其它网络上其实也很多,基本上就是 RDBMS 加上 Redis 缓存。

这方面的阅读列表: