关于构建feed系统的思考
feed系统就是类似于weibo和twitter的通过用户关注行为来帮助用户聚合的获取内容的系统.
feed系统有两种模式,push
和pull
.
push
模式就是当一个用户产生内容后,系统将内容推送到该用户所有粉丝的收件箱
中,当粉丝数很小的时候这也许是一个不错的选择,但是如果有几百万甚至千万的粉丝的时候,假设推送到一个用户收件箱要1ms,那么全部推送完要多久?某些用户收到该内容可能要延迟几十分钟到几小时.而且push
模式会用尽系统所有的资源,即使某些粉丝永远不会再使用该系统.pull
模式就是当用户请求feed流时,系统到该用户的所有关注用户的发件箱
中查询内容,聚合排序后返回给用户,省去了push
模式的延迟,可以说是按需使用系统资源.但如果用户关注了2000人,这样查询的性能会成为首要面对的问题,可能需要做好shard,并行的查询再统一排序.
两种模式各有各的优势,但劣势也非常明显.
如果想构建一个实时的,高性能的feed系统,我们要做什么呢?
- 用户活跃度统计子系统
push
和pull
混合使用- 活跃用户采用
push
模式 - 按照用户活跃度采用不同的
push
优先级 - 僵尸用户采用
pull
模式
- 活跃用户采用
- 优化
收件箱
和发件箱
的数据结构 - 缓存,活跃用户的数据一定要在内存中
- 并行化
这样就通过分级,减少实时push
的用户数量,达到准实时的效果,并且降低单次push
和pull
的时间,提高了系统整体的速度和吞吐量.
需要一些什么样的中间件呢?
- 消息中间件,主要要完成推送任务的缓冲,异步化推送,譬如kafka,rabbitMQ.
- 高查询性能的可扩展的能够支持列表设计的数据库,
pull
极其的快,存储用户的发件箱
,譬如mysql. - 极其快速的可扩展的能够支持列表设计的数据库,存储活跃用户的
收件箱
,譬如redis,ssdb. - 极其快速的可扩展的支持linkedhash数据结构的数据库,存储用户的
粉丝
列表,譬如redis的zset. - 极其快速的内存数据库,存储活跃用户列表,譬如redis.
- 有一个支持multi process的RPC框架那就更好了.
大概想了这么多,不知道这样的系统能支撑一个什么样的数量级,至于去年听的weibo分享时说的streaming api我也不清楚具体是什么东西,不过应该很吊的样子,可能到他们的量级才会遇到那样的问题,我这个阶段也就只能思考到这个程度了,前几天还看到highscalability上有用elastic search做的feed流,感觉他们也算另辟蹊径吧.