百万用户时尚分享网站feed系统扩展实践

栏目: 数据库 · 发布时间: 6年前

内容简介:百万用户时尚分享网站feed系统扩展实践

Fashiolista 是一个在线的时尚交流网站,用户可以在上面建立自己的档案,和他人分享自己的以及在浏览网页时看到的时尚物品。目前,Fashiolista的用户来自于全球100多个国家,用户达百万级,每日分享的时尚物品超过500万。作为一个以社交、分享的网站,feed系统占据了网站的核心架构,Fashiolista的创始人兼CTO Thierry Schellenbach撰写了一篇博客,分享了自家网站feed系统建设的经验, 译文如下:

Fashiolista最初是我们作为兴趣在业余时间开发的一个项目,当初完全没有想到它会成长为规模如此大的在线时尚交流网站。最早的版本开发用了大概两周的时间,当时feed信息流推送系统相当简单。在这里分享一些我们扩展feed系统的经验。

百万用户时尚分享网站feed系统扩展实践

对于许多大型的创业公司,如Pinterest、Instagram、Wanelo和Fashiolista来说,feed是一个核心组件。在Fashiolista网上的 flat feedaggregated feednotification 系统功能都是靠feed系统来支撑的。本文中将介绍我们在扩展feed系统中遇到的问题,以及你自己方案中的设计决策。随着越来越多的应用依赖于feed系统,理解feed系统的基本工作原理变得至关重要了。

另外,Fashiolista的feed系统 Python 版本—— Feedly 已经开源了。

Feed简介

feed系统的扩展问题曾引起过广泛关注,这个解决方案是为了在网络拥挤的情况下,构建一个类似于Facebook新鲜事feed、Twitter流或Fashiolista的feed页面。这些系统的共同点在于向用户展示其关注的人的动态,我们就是基于 这个标准 来构建动态数据流的,诸如“Thierry在Fashiolista列表中添加了一件服饰”或“Tommaso发布了一条twitter”。

构建这个feed系统用到了两个策略:

  1. 拉取(Pull),读取的过程中收集feed。
  2. 推送(Push),写的过程中提前计算好feed。

大多数实时在线应用程序会使用这两种方法的组合,将动态推送给你的粉丝的过程被称为消息分发(fanout)。

历史和背景

Fashiolista的feed系统经过了三次重大改进。第一个版本基于PostgreSQL数据库,第二个版本使用 Redis 数据库,目前的版本采用Cassandra数据库。为了便于读者更好的理解这些版本更替的时间和原因,笔者会首先介绍一些背景知识。

第一部分——数据库

百万用户时尚分享网站feed系统扩展实践 第一版本的数据库查询语句很简单,类似于这种:

select * from love where user_id in (...)

令人惊讶的是这个系统的强健性还不错。当love(类似于“赞”了某件服饰)的数量达到百万时,它运行得很好,超过500万时,依然没有问题。我们还打赌说这个系统不能支持千万的数量级,但是当love到达千万时,它依然运行得很好。这个简单的系统支撑着我们的系统达到了百万的用户和过亿的love,期间只进行了一些小改动。之后随着用户的增多,这个系统开始出现波动,部分用户的延时长达数秒,在参考了很多关于feed系统的架构设计之后,我们开发了第一个基于Redis的Feedly。

第二阶段——Redis和Feedly

我们为每个用户建立一个用Redis存储的feed,当你love了一件服饰时,这个动态会分发给你所有的粉丝。我们尝试了一些小技巧来减少内存的消耗(笔者会在下面具体介绍),Redis的启动和保持确实比较简单。我们使用 Twemproxy 在几台Redis机器上进行共享,使用 Sentinel 做自动备份。

Redis是一个好的解决方案,但是几个原因迫使我们不得不寻找新的方案。首先,我们希望支持多文档类型,而Redis返回数据库查询更困难,并且提高了存储需求。另外,随着业务的增大,数据库回滚也变得越来越慢。这些问题只能靠在Redis上存储更多的数据来解决,但是这样做的成本太高了。

第三阶段——Cassandra和Feedly

通过比较 HBaseDynamoDBCassandra2.0 ,我们最终选择了Cassandra,因为它拥有几个移动部件,Instagram使用的数据库就是Cassandra,并且 Datastax 为它提供支持。Fashiolista目前在flat feed中完全采取推送流,聚合feed采用推送和拉取混合的技术。我们在每个用户的feed中最多保存3600条动态,目前占用了2.12TB的存储空间。由明星用户带来的系统波动我们也采取了一些方式进行缓解,包括:优先队列、扩大容量和自动扩展等。

百万用户时尚分享网站feed系统扩展实践

Feed设计

笔者认为Fashiolista设计的改进过程非常有代表性,在构建一个feed系统时(尤其是使用Feedly)有几个重要的设计问题需要考虑。

1.非规范化Vs规范化

规范化的方法是,你关注的人的feed列表中是每条动态的ID,非规范的存储是动态的所有信息。

仅存储ID可以大幅度减少内存消耗,然而这意味着每次加载feed都要重新访问数据库。如何选择取决于你在进行非规范化存储时,复制数据的频率。比如构建一个消息通知系统和一个feed系统有很大的区别:通知系统中每个动作的发生只需要被发送给几个用户,而feed系统中每个动态的数据可能要被复制给成千上万的粉丝。

另外,如何选择取决于你的存储架构,使用Redis时,内存是需要特别注意的问题;而使用Cassandra要占用大量的存储空间,但是对于规范化数据来说使用并不简单。

对于feed通知和基于Cassandra构建的feed,笔者建议将你的数据非规范化。而基于Redis的feed你需要最小化内存消耗,并保持数据规范化。采用Feedly可以轻松实现两种方案。

2.基于生产者的选择性分发

Yahoo的Adam Silberstein等人所著的论文中 ,提出了一种选择性推送用户feed的方法, Twitter 目前也在使用类似的方法。明星用户的消息分发会给系统带来突然和巨大的负载压力,这意味着必须要预留出额外的空间来保持实时性。这篇论文中建议通过选择性地分发消息,来减少这些明星用户带来的负载。Twitter采用了这个方法后,在用户读取时才加载这些明星用户的tweet,性能得到了大幅度提升。

3.基于消费者的选择性分发

另外一种选择性分发方式是指对那些活跃用户(比如过去一周登录过的用户)分发消息。我们对这个方法进行了修改,为活跃用户存储最近的3600条动态,为非活跃用户存储180条,读取180条之后的数据需要重新访问数据库,这种方式对于非活跃用户的体验不太好,但是能有效降低内存消耗。

Silberstein等人认为最适合选择性推送模式的情境是:

  1. 生产者偶尔生产动态信息
  2. 消费者经常请求feed

遗憾的是Fashiolista还不需要如此复杂的系统,很好奇业务要达到多少数量级才会需要这种解决方案。

4.优先级

一个替代的策略是在分发任务时采取不同的优先级,将给活跃用户的分发任务设为高优先级,向非活跃用户的分发任务设为低优先级。Fashiolista为高优先级的用户预留了一个较大的缓存空间,来处理随时的峰值。对于低优先级用户,我们靠自动扩展和点实例。在实践中,这意味着非活跃用户的feed会有一定的延时。使用优先级降低了明星用户对系统的负载压力,虽然没有解决根本问题,但大幅度降低了系统负载峰值的量级。

5.Redis Vs Cassandra

Fashiolista和 Instagram 都经历了从Redis开始,然后转战Cassandra的过程。笔者之所以会推荐从Redis开始是因为Redis更容易启动和维持。

然而Redis存在一定的限制,所有的数据需要被存储在RAM中,成本很高。另外,Redis不支持分片,这意味着你必须在结点间分片(Twemproxy是一个不错的选择),这种分片很容易,但是添加和删除节点时的数据处理很复杂。当然你可以将Redis作为缓存,然后重新访问数据库,来克服这个限制。但是随着访问数据库的成本越来越高,笔者建议还是用Cassandra代替Redis。

Cassandra Python的生态系统正在发生巨变, CQLEnginePython-Driver 都是很优秀的项目,但是它们需要投入一定的时间去学习。

结论

在构建自己的feed解决方案时,有很多因素需要在节点分片时考虑:选择何种存储架构?如何处理明星用户带来的负载峰值?非规范化数据到何种程度?笔者希望借助这篇文章能够为你提供一些建议。

Feedly不会为你做任何选择,这仅是一个构建feed系统的框架,你可以自己决定内部的技术细节。可以看Feedly的介绍进行了解或参看 操作手册构建一个Pinterestsque应用程序

请注意只有数据库中的用户达到百万时,你才会需要解决这个问题。在Fashiolista简单的数据库解决方案就支撑我们达到了百万用户和过亿的love。

更多关于feed系统的设计,笔者强烈建议看一下这些文章:


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Parsing Techniques

Parsing Techniques

Dick Grune、Ceriel J.H. Jacobs / Springer / 2010-2-12 / USD 109.00

This second edition of Grune and Jacobs' brilliant work presents new developments and discoveries that have been made in the field. Parsing, also referred to as syntax analysis, has been and continues......一起来看看 《Parsing Techniques》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具