Java基础、中级、高级、架构面试资料

设计一个社交网站的点赞最佳方案

JAVA herman 4927浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

我搜了一下,发现网络上很少有关于社交网络的点赞功能的设计和实现。究其原因是很多人没遇到过这样的需求,真实场景太过于复杂,写出来的文章容易被打脸!而我今天就是冲着打脸来的!

在开始之前,我们参考一下微博的点赞案例!

大V、明星的一条微博的点赞数可能有几十万,甚至百万以上。那么这个“点赞”功能是如何设计的呢?

有的人说,这还不好设计,一张表搞定,看下面的表:

CREATE TABLE `t_link` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `art_id` bigint(20) DEFAULT NULL COMMENT '文章ID',
  `user_id` bigint(11) DEFAULT NULL COMMENT '点赞用户id',
  `like_time` datetime DEFAULT NULL COMMENT '点赞时间',
  `status` int(11) NOT NULL COMMENT '状态',
  PRIMARY KEY (`id`)
);

然后,每次文章有人点赞时就加一条记录,取消点赞就update一条记录。

我们先不说这样设计合不合理,普通的博客,这样设计没什么问题。因为访问量就小,直接操作MySQL数据库问题也不大。但是问题在于当你的用户量大,访问量大的时候,类似微博的大V之类的,粉丝众多的时候,就像我们开头所说的一篇文章上百万个赞很正常!

那么这个时候,你再直接操作数据库,系统肯定是要玩蛋的!

这个时候,我猜有人会想到了Redis。嗯,用 Redis 能起到一定的作用。

关于点赞,我们先操作 Redis,等一定的时间,或者一定的数据量,然后再批量的持久化到数据库。

但是呢?用 Redis 也有几个问题,那就是不能让所有的数据都缓存起来吧!微博每天产生那么多文章,产生那么多的点赞记录。光存储在磁盘那数据量也大的超乎想象吧!微博现在的 Redis 都是几十T的大小。光缓存点赞数据,肯定不行。我们得找出哪些是热门的数据,然后把热门的给缓存起来。粉丝小的,几天以前甚至是很久以前的是不是缓存的必要性就得考虑了!

再说上面的数据表设计,每天会产生多少的点赞记录,不可想象。你一定得分表分库设计吧!

分表分库你是根据什么分呢?不管你根据什么分,使用的时候都会遇到麻烦!比如,查询哪些用户点了赞,查询我的好友中谁点了赞,查询某个人对某些文章点了赞等。你分表分库后,查询就不方便了。

再说上面引入 Redis 后,也会带来很多新的问题!比如:开发复杂,这个比直接写mysql的方案要复杂很多, 需要考虑的地方也很多;不能保证数据安全性,redis挂掉的时候会丢失数据, 同时不及时同步redis中的数据, 可能会在redis内存置换的时候被淘汰掉等。

社交网站点赞功能设计

但是你不能说 Redis 有缺点你就不用它吧,用还是要用。关键就看你如何用?下面说说我的打脸思路!

在redis中弄一个set存放所有被点赞的文章,post_user_like_set_{$post_id},对每个post以post_id作为key, 搞一个set存放所有对该post点赞的用户;

post_user_like_{$post_id}_{$user_id} 将每个用户对每个post的点赞情况放到一个hash里面去。

为啥用hash?只所以用hash是因为完全可以用hash来存储一个点赞的对象, 对应数据库的一行记录。

当然有同学会说用key, value也可以, 将所有的数据序列化(json_encode等),后全部放到value里面去。 hash可以很方便的修改某个字段, 而序列化和反序列化的操作。

post_{$post_id}_counter 对每个post维护一个计数器, 用来记录当前在redis中的点赞数,这里我们只用counter记录尚未同步到mysql中的点赞数(可以为负), 每次刷回mysql中时将counter中的数据和数据库已有的赞数相加即可。

用户点赞/取消赞:获取user_id, post_id, 查询该用户是否已经点过赞, 已点过则不允许再次点赞,这里需要注意的是用户点赞的记录可能在数据库中, 也可能在缓存中, 所以查询的时候缓存和数据库都要查询, 缓存没有再查询数据库。

关于点赞就写这么多吧,主要是在往下写,脸打的更痛。我就抛个砖,等其他各路大神来反击写文章吧!

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » 设计一个社交网站的点赞最佳方案