文章目录
点赞系统的高并发
1.项目背景
项目背景,基于B站视频中的点赞,投币功能应运而生的高并发案列,同样在现代很火的视频共享网站,比如抖音短视频,点赞是重要的交互功能。从用户的角度来说,推荐系统可以根据用户点赞给用户推荐更适合个人口味的视频。
1.1 场景
- 从两个维度进行考虑,其一是用户,另一个就是视频的维度
1.2用户
- 用户点赞视频
- 用户取消某个视频点赞
- 获取用户视频点赞总数,展示用户点赞过的视频总数
- 获取用户点赞视频列表,展示用户已经点赞过的视频
- 用户是否已经点赞过某些视频,用户在前端看到的视频列表,需要展示用户是否已经赞过
1.3视频
- 视频点赞数,视频的点赞用户数
- 视频点赞用户列表,点赞过的视频的用户列表
1.4目标
点赞,投币的设计目标是:高性能、高可用、可拓展
1.5高性能
获取点赞数,是否点赞视频的流量QPS比较高且需要快速的响应,否则影响用户体验
1.6高可用
用户对点赞行为感知比较明显,如果点赞服务不可以用,会影响用户的体验。服务故障需要自动恢复,否则用户可能会感知到数据缺失,尤其是点赞量少的情况下。
1.7 可拓展性
用户和视频数据量随着平台在不断发展会快速增长,点赞的流量也会不断增大。所以点赞服务需要在未来应对增加的流量和数据量。
2.在储存和数据一致性上的方案
2.1 储存方面
点赞服务需要储存海量的点赞数据时,在考虑成本的情况下我们可以采取传统数据库的方案。比如Mysql的分库分表
,但是带来了响应的维护和管理成本。
如果不考虑成本,可以采用更简单的NewSql方案
,比分库分表方案简单。可以使用开源的数据库,比如Tidb,但是自己部署管理带来很大的运维成本。也可以直接使用商业化的方案,但是比较贵,比如Tidb的商业版本,Spanner等。
通过分库分表或者NEWSql都可以扩展数据库存储能力,并通过从库提高数据并发查询能力,主从和集群则提供了数据库高可用。
2.2存在性判断
是否点赞本质上就是存在性判断,判断某个用户是否点赞了某些视频。
点赞数据量比较大,存在性判断需要非常快的速度。并发量也比较高,否则会影响用户的体验。
如果使用数据库的话,数据库的查询性能也不太好,会给数据造成比较大的压力
;如果使用Redis存储(Set、Zet),那么海量的数据会消耗比较多的资源。一般常用的存在性判断使用布隆过滤器,随着点赞数量的删除和增加,需要不断动态的维护,比如扩容来提高准确度。
- 什么是布隆过滤器?
官方文档->布隆过滤器阿里巴巴开发社区:https://developer.aliyun.com/article/773205
布隆过滤器,实际上是一个二进制向量和一系列随机映射函数,主要用于判断一个元素是否存在一个集合中,具体还是看上面的文档吧
2.2计数
获取用户点赞数和视频点赞数也是请求频率比较高的场景,比如展示用户和视频信息的时候。如果每次都去数据库 count 的话,数据库扛不住。所以一般选择缓存点赞计数
,但是缓存就会带来数据一致性问题。解决方法就是依据数据库的点赞数据动态的去校对缓存的数据。
计数数据存储在 Redis,而 Redis 可以保证高性能、高可用、可拓展
- 这里丢一个问题,如何保证数据一致性的问题
2.3异步
有点赞或者取消点赞行为时,会更新数据库点赞数据,需要同步到计数和布隆过滤器等。通过使用数据中间件,比如 canal 消费数据库日志的方式可以和业务解耦,把数据库更新数据的操作分发到不同的消息队列给不同的服务处理。比如做点赞计数的加减、更新布隆过滤器等。
- 视频服务:提供视频内容。
- 用户服务:提供用户数据。
- Like 服务:点赞服务,提供点赞相关的接口。点赞、取消点赞、是否点赞等。
- 用户计数服务:统计用户点赞数,并提供用户点赞数查询。
- 视频计数服务:统计视频点赞数,并提供视频点赞数查询。实际上两个计数服务可以合并成一个大的计数服务。
- API 网关:对外提供接口服务(移动端、前端等)。聚合其他基础服务的数据。比如返回前端的视频会聚合视频点赞数、用户是否点赞等信息。
- 数据库:提供点赞数据存储和查询。
- Redis:存储布隆过滤器、计数器等数据。
- Canal:把数据库数据的更新的数据改动同步出来,并分发到 - - MQ 触发对应的服务处理。
3.优化
点赞数据可能过一段时间就会变成比较少甚至不访问的数据,有些用户可能不经常登陆或使用。Redis 是内存数据库,存储资源成本比较高
。使用混合存储把冷数据存储在磁盘
,当需要的时候混合存储自动把冷数据加载到内存
,这样可以在性能和成本之间得到一个比较好的平衡