Django帖子点赞与浏览量统计方案选型:最优方案及Instagram实践
Django帖子点赞与浏览量统计方案分析
Instagram的实现思路
Instagram采用的是异步更新计数器+缓存层的组合方案:
- 核心点赞记录(用户-帖子的关联关系)存在独立表中,用于保证数据准确性和后续数据分析;
- 帖子表中用整数字段存储点赞数、浏览量等统计值,前端展示时直接读取该字段或缓存中的值;
- 用户触发点赞/取消赞、浏览操作时,先更新缓存中的统计值保证实时性,再通过异步任务同步数据库中的计数器和核心记录,避免实时操作带来的数据库性能瓶颈。
三种方案的优缺点分析
方案1:反向外键关联动态统计
- 优势:数据绝对一致,无需维护额外统计字段,逻辑简单直接;
- 劣势:性能瓶颈明显,当帖子点赞量上万后,每次
like_set.count()都会触发关联表的全表扫描,并发请求下数据库压力陡增,几乎无法支撑大规模用户量。
方案2:整数字段存储统计值
- 优势:读取性能极高,直接读取字段值即可,数据库查询成本极低;
- 劣势:需要额外保证统计值与真实点赞记录的一致性,并发场景下容易出现竞态问题(比如多个请求同时点赞导致计数不准),需要事务或异步机制辅助。
方案3:多对多字段统计数量
- 优势:Django ORM封装完善,调用
post.likes.count()即可获取点赞数,代码可读性强; - 劣势:本质和方案1相同,底层还是对关联表执行count操作,数据量大时性能急剧下降,且多对多关联表的维护成本会随着数据量增长而升高。
兼顾低成本与扩展性的最优选择
优先选择方案2(整数字段存储统计值)+ 缓存+轻量异步任务的组合,具体实现要点:
- 帖子模型新增字段:
class Post(models.Model): # 其他业务字段 like_count = models.IntegerField(default=0) view_count = models.IntegerField(default=0)
- 单独创建点赞记录模型,添加唯一约束避免重复点赞:
class Like(models.Model): post = models.ForeignKey(Post, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) class Meta: unique_together = ('post', 'user')
- 点赞/取消赞逻辑:
- 检查用户是否已点赞,未点赞则创建
Like实例,通过异步任务(如Django Q、Celery)给like_count加1; - 取消赞则删除
Like实例,异步给like_count减1;
- 检查用户是否已点赞,未点赞则创建
- 浏览量统计:
- 用Redis缓存记录用户的浏览标识(如
user_{user_id}_viewed_post_{post_id}),避免同一用户重复计数; - 缓存验证通过后,异步更新
view_count;
- 用Redis缓存记录用户的浏览标识(如
- 前端展示:优先从Redis缓存读取统计值,缓存未命中时再从数据库读取,同时后台异步更新缓存。
这种方案初期开发成本低(无需复杂架构),当用户量增长时,仅需扩容缓存和异步任务队列即可支撑更高并发,扩展性强。
内容的提问来源于stack exchange,提问作者Awm
相关产品推荐
相关产品推荐

