这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天。
本文以 CC-BY-SA 4.0 发布。
点赞系统
基本上所有社交网络平台上都会有点赞系统的存在,微博、朋友圈、掘金、抖音莫不如此。 当然,不同平台的点赞对应的功能有一些差别。 汇总一下,一个点赞系统的需要提供的功能大致如下:
- 某一用户个人的点赞记录
- 某一对象被点赞的计数
- 某一对象被点赞的具体记录
在数据量较大时,从对象被点赞的具体记录中(例如通过 SELECT COUNT(*) ...
)
来汇总得出点赞的计数开销较大,因此点赞系统通常被分为点赞具体记录以及计数系统两部分。
计数系统
计数系统和点赞系统的其它部分是相对独立的。 评论计数、发文计数、关注计数等等都可以独立出一个共用的计数系统来使用。
[WeiDesign]微博计数器的设计(下) · Cydu's Blog 这篇文章基于微博级别的数据量及并发给出了非常详细的论述。 文章里从简单到复杂大概分为三种思路:
- 关系数据库:
- 最开始可以直接
UPDATE ... SET count = count + 1
; - 数据量上来了可以用 Redis 等缓存;
- 缺点:数据量到了微博数量级后分库分表麻烦,高并发也有缓存失效问题。
- 最开始可以直接
- 纯 Redis:
- 缺点:内存开销大,一个字“贵”。
- 自己写一个类 Redis 的计数专用数据系统实现:
- 这就不是我等凡人能触及的领域了。
总之,如果没有到微博数量级的数据量和并发的话, 大概 RDBMS + 多级缓存 + 一定程度的操作合并就已经能够满足大多数需求了。
计数系统还可以提的一点是不要用 Cassandra 的 counter 来实现,详情可以看 Cassandra counter columns: Nice in theory, hazardous in practice。 总而言之是开销极大。
点赞具体记录
这部分内容记录了用户点赞过什么以及点赞了某一对象(如某条微博)的人。 一般来说,用户会希望有一个记录了自己点赞记录的列表, 但是反过来的话,某一对象的点赞列表不是所有平台都支持。 (例如掘金,你看不到一篇文章具体是谁点赞的,只有作者会收到通知。 掘金这部分更多是通知系统负责,而不是点赞系统。)
两个需求:
- (一般必须)用户的点赞记录
- (可能不需要)某一条微博的点赞人列表
这两个需求说到底就是一个索引还是两个索引的问题。 一个索引的话,用 RDBMS 的话来说,直接用主键索引即可,不需要多余的索引, 写入性能会有提升,也能省点储存空间。
此外,如果用的不是 RDBMS 而是 NoSQL 的话(如 Redis),一个索引哈系表轻轻松松, 但是两个索引的话就会需要考虑原子操作了(如 Redis 的 Lua 脚本)。
这方面的文章掘金上和其它网络上其实也很多,基本上就是 RDBMS 加上 Redis 缓存。
这方面的阅读列表: