关于构建feed系统的思考

feed系统就是类似于weibo和twitter的通过用户关注行为来帮助用户聚合的获取内容的系统.

feed系统有两种模式,pushpull.

  • push模式就是当一个用户产生内容后,系统将内容推送到该用户所有粉丝的收件箱中,当粉丝数很小的时候这也许是一个不错的选择,但是如果有几百万甚至千万的粉丝的时候,假设推送到一个用户收件箱要1ms,那么全部推送完要多久?某些用户收到该内容可能要延迟几十分钟到几小时.而且push模式会用尽系统所有的资源,即使某些粉丝永远不会再使用该系统.

  • pull模式就是当用户请求feed流时,系统到该用户的所有关注用户的发件箱中查询内容,聚合排序后返回给用户,省去了push模式的延迟,可以说是按需使用系统资源.但如果用户关注了2000人,这样查询的性能会成为首要面对的问题,可能需要做好shard,并行的查询再统一排序.

两种模式各有各的优势,但劣势也非常明显.

如果想构建一个实时的,高性能的feed系统,我们要做什么呢?

  • 用户活跃度统计子系统
  • pushpull混合使用
    • 活跃用户采用push模式
    • 按照用户活跃度采用不同的push优先级
    • 僵尸用户采用pull模式
  • 优化收件箱发件箱的数据结构
  • 缓存,活跃用户的数据一定要在内存中
  • 并行化

这样就通过分级,减少实时push的用户数量,达到准实时的效果,并且降低单次pushpull的时间,提高了系统整体的速度和吞吐量.

需要一些什么样的中间件呢?

  • 消息中间件,主要要完成推送任务的缓冲,异步化推送,譬如kafka,rabbitMQ.
  • 高查询性能的可扩展的能够支持列表设计的数据库,pull极其的快,存储用户的发件箱,譬如mysql.
  • 极其快速的可扩展的能够支持列表设计的数据库,存储活跃用户的收件箱,譬如redis,ssdb.
  • 极其快速的可扩展的支持linkedhash数据结构的数据库,存储用户的粉丝列表,譬如redis的zset.
  • 极其快速的内存数据库,存储活跃用户列表,譬如redis.
  • 有一个支持multi process的RPC框架那就更好了.

大概想了这么多,不知道这样的系统能支撑一个什么样的数量级,至于去年听的weibo分享时说的streaming api我也不清楚具体是什么东西,不过应该很吊的样子,可能到他们的量级才会遇到那样的问题,我这个阶段也就只能思考到这个程度了,前几天还看到highscalability上有用elastic search做的feed流,感觉他们也算另辟蹊径吧.