微博系统动态feed数据库设计。

Milu
  • 1.3k

1、应用场景:比如QQ空间、微博等的好友动态

XX分享了图片。
XX发布了新日志。

不过我这个系统比较简单,就像instagram,只有分享图片,然后关注者可以在动态里面查看到。

2、目前了解的,比如新浪微博,一般采用推拉模式

推:推送
拉:查询

3、我的想法是找一个能应对产品运营初期的方案,不要用太复杂的技术和软硬件实现。只是能让产品快速上线,又能应对早期一定量的用户。

4、说说我目前的想法

4-1、如果我采用推:比如一个用户有几万粉丝,那么就要在发布的时候,产生几万条推数据。我感觉数据量和操作都比较费时。当然了,可以异步等等,我在新浪微博的技术架构ppt里面看到用比较复杂的技术来实现,比如什么MemcacheQ。
此外,新浪微博说第二版的时候才采用MemcacheQ,第一版就简单的推模式。我不知道我假设的一个用户几万粉丝,当他发布一条消息的时候,服务器insert几万条记录速度是不是很慢。当然了,运营初期,一个用户几万粉丝这种情况应该没多少。比较倾向这种方案,因为有利于以后的扩展。

4-2、如果拉吧,就是用户登录,查询他所关注的用户的动态。查询sql大概如下:

select * from 动态表 where uid in(所关注的uid)
这个“所关注的uid”,如果有几千、几万怎么办?还一个in查询,速度肯定慢了。

或许吧,做点分表,分成几张表,一个星期的数据、一个月的数据等等,再做点缓存,这样下来,查询速度应该差强人意了。

所以,总结之下,都没特别特别满意的方案。有做过类似需求的同志吗?指点一下,谢谢。

回复
阅读 13.9k
4 个回答

http://gglinux.com/2017/03/06...

推方式

推方式,是发生在用户触发行为(发布新的动态,关注某个人,点赞)的时候。在触发时,用户的自身行为会记录到对应的行为表中,其次用户的行为也会记录到自己的粉丝对应动态表中。
这里写图片描述

用户A发布新的帖子(动态),帖子记录到帖子表(主表)中。
发帖行为塞到队列(Redis List)中。触发异步操作,消费者会先读取用户的粉丝列表(uid分表),依次写入到用户的动态表(uid分表)中。
前端读取用户动态Feed,使用过滤条件,读取用户的动态表(关联查询帖子表)。
使用推方式,对需求变更是易适应的。为什么这么说呢?因为用户每一次的行为,我们都有存储相应的数据(数据模型)。即使变更,只需更改逻辑层代码。另外性能较好,后台数据已经准备好了,无需复杂的SQL查询。当然这样做,也存在很多弊端。1. 如果在用户A发完动态后,其粉丝B取消关注了A。在这个时间差内,内容已经推送给粉丝B了。2. 数据量存储成本较大,假如一个用户的粉丝数是100万,在发帖后会写入100万条数据。

拉方式

拉方式,是发生在粉丝拉取Feed时。粉丝拉取自己的动态,首先会检索自己的关注用户(uid分表)。得到关注的uid之后,再根据uid去查询关注用户发布的帖子。
这里写图片描述

拉的模式相对是比较简单易实现的,另外对用户关系变更(新增,删除用户)是敏感的。其次也不存在数据存储压力。但在查询的时候,对帖子表本身压力是很大的。尤其是用户本身关注的人很多的话,会有很严重的性能问题。

拉方式优化-伪实时拉取

用户在登录APP时,会发送用户活跃态到服务端。活跃信号塞到队列中,消费者依次读取活跃态uid,得到用户的关注者列表。得到关注者列表后,会去帖子表,查询关注人的发布的帖子。写到用户自己的Feed中。
这里写图片描述

这种方式和对拉方式而言,能有效避免接口性能问题,相当于通过定时任务提前把用户的动态Feed跑出来。和推方式比较,推是比较盲目的,这种方式只需针对活跃用户即可,能避免存储浪费。缺点在于实时性不好,用户登录APP后马上进入自己的Feed页,此时如果后台用户动态还没跑完,接口读取的就是历史数据了。当然这种方式不适合知乎,微博这种类型的APP的。

拉方式优化-分区拉取

分区拉取,是为了避免频繁查询单一帖子表所采用的一种优化手段。通过对帖子按照时间片分表,每次查询都能均摊到不同的表中,以此减轻主表的压力。

推方式优化-定时推

定时推,是以常驻进程的方式读取用户的发帖行为,再批量写入到粉丝的动态表中。这种方式和推方式差不多,只不过可以对多个发帖行为做聚合。

推方式优化-特定用户推

特定用户推,是推方式的一种优化方法。用户发送帖子时,只对活跃的粉丝用户写入。当然活跃用户的判定策略,是需要商定的。

综合

以上几种方案,都有自己的利弊和适用场景。选择最适合自己的就是最好的。最后,我们采用了伪实时拉取这种方式。因为我们的需求是对点赞用户的聚合展示,类似于下图知乎这种。
这里写图片描述

本身点赞行为会存储在两种类型的表(以帖子ID的点赞分表,以用户ID的点赞分表)中,如果单纯以拉方式话,会比较难处理的,而且有性能问题。其次,点赞这个行为的重要程度还不足以我们批量去存储的。

1.是RabbitMQ吧?
2.推送可以放到后端来做,python写个daemon后端跑(如果本身就是python写的那更方便),发布一条微博同时发送一个信号到Python。 发送/删除/发起评论/删除评论 都放到队列来做。
3.In查询很快
4.建议看一下记事狗微博的做法。

如果关注了1W个用户怎么办?

你知道吗?

宣传栏