搜索
❏ 站外平台:

Tumblr 架构设计

| 2013-05-26 21:58      

老的Tumblr构架

  • Tumblr最开始是托管在Rackspace上的,每个自定义域名的博客都有一个A记录。当2007年Rackspace无法满足其发展速度不得不迁移 时,大量的用户都需要同时迁移。所以他们不得不将自定义域名保留在Rackspace,然后再使用HAProxy和Varnish路由到新的数据中心。类 似这样的遗留问题很多。
  • 开始的架构演进是典型的LAMP路线
    • 最初用PHP开发,几乎所有程序员都用PHP
    • 最初是三台服务器:一台Web,一台数据库,一台PHP
    • 为了扩展,开始使用memcache,然后引入前端cache,然后在cache前再加HAProxy,然后是非常奏效的MySQL sharding
    • 采用“在单台服务器上榨出一切”的方式。过去一年已经用C开发了两个后端服务:ID generatorStaircar(用Redis进行Dashboard通知)
  • Dashboard采用了“扩散-收集”方式。当用户访问Dashboard时将显示事件,来自所关注的用户的事件是通过拉然后显示的。这样支撑了6个月。由于数据是按时间排序的,因此sharding模式不太管用。

新的构架

  • 由于招人和开发速度等原因,改为JVM为中心
  • 目标是将一切从PHP应用改为服务,使应用变成请求鉴别、呈现等诸多服务之上的薄层。
  • 选择了Scala 和 Finagle
    • 在团队内部有很多人具备Ruby和PHP经验,所以Scala很有吸引力。
    • Finagle是选择Scala的重要因素之一。这个来自Twitter的库可以解决大多数分布式问题,比如分布式跟踪、服务发现、服务注册等。
    • 转到JVM上之后,Finagle提供了团队所需的所有基本功能(Thrift, ZooKeeper等),无需再开发许多网络代码,另外,团队成员认识该项目的一些开发者。
    • Foursquare和Twitter都在用Finagle,Meetup也在用Scala。
    • 应用接口与Thrift类似,性能极佳。
    • 团队本来很喜欢Netty,但不想用Java,Scala是不错的选择。
    • 选择Finagle是因为它很酷,还认识几个开发者。
    • 之所以没有选择Node.js,是因为以JVM为基础更容易扩展。Node的发展为时尚短,缺乏标准、最佳实践以及大量久经测试的代码。而用Scala的 话,可以使用所有Java代码。虽然其中并没有多少可扩展的东西,也无法解决5毫秒响应时间、49秒HA、4万每秒请求甚至有时每秒40万次请求的问题。 但是,Java的生态链要大得多,有很多资源可以利用。
  • 内部服务从C/libevent为基础正在转向Scala/Finagle为基础。
  • 开始采用新的NoSQL存储方案如HBase和Redis。但大量数据仍然存储在大量分区的MySQL架构中,并没有用HBase代替MySQL。
  • HBase主要支持短地址生产程序(数以十亿计)还有历史数据和分析,非常结实。此外,HBase也用于高写入需求场景,比如Dashboard刷新时一 秒上百万的写入。之所以还没有替换HBase,是因为不能冒业务上风险,目前还是依靠人来负责更保险,先在一些小的、不那么关键的项目中应用,以获得经 验。
  • MySQL和时间序列数据sharding(分片)的问题在于,总有一个分片太热。另外,由于要在slave上插入并发,也会遇到读复制延迟问题。
  • 此外,还开发了一个公用服务框架:
    • 花了很多时间解决分布式系统管理这个运维问题。
    • 为服务开发了一种Rails scaffolding,内部用模板来启动服务。
    • 所有服务从运维的角度来看都是一样的,所有服务检查统计数据、监控、启动和停止的方式都一样。
    • 工具方面,构建过程围绕SBT(一个Scala构建工具),使用插件和辅助程序管理常见操作,包括在Git里打标签,发布到代码库等等。大多数程序员都不用再操心构建系统的细节了。
  • 40台服务器采用HAProxy进行负载均衡,Varnish进行缓存.
  • 200台数据库服务器中,很多是为了提高可用性而设,使用的是常规硬件,但MTBF(平均故障间隔时间)极低。故障时,备用充足。
  • 500台服务器运行Apache和其他PHP程序。
  • 6个为了支持PHP应用的后端服务,并有一个小组专门开发后端服务。新服务的发布需要两到三周,包括Dashboard通知、Dashboard二级索引、短地址生成、处理透明分片的memcache代理。
  • 其中在MySQL分片上耗时很多。虽然在纽约本地非常热,但并没有使用MongoDB,他们认为MySQL的可扩展性足够了。
  • Gearman用于会长期运行无需人工干预的工作。
  • 可用性是以达到范围(reach)衡量的。用户能够访问自定义域或者Dashboard吗?也会用错误率。
  • 历史上总是解决那些最高优先级的问题,而现在会对故障模式系统地分析和解决,目的是从用户和应用的角度来定成功指标。
  • 最开始Finagle是用于Actor模型的,但是后来放弃了。对于运行后无需人工干预的工作,使用任务队列。而且Twitter的util工具库中有Future实现,服务都是用Future(Scala中的无参数函数,在与函数关联的并行操作没有完成时,会阻塞调用方)实现的。当需要线程池的时候,就将Future传入Future池。一切都提交到Future池进行异步执行。
  • Scala提倡无共享状态。由于已经在Twitter生产环境中经过测试,Finagle这方面应该是没有问题的。使用Scala和Finagle中的结 构需要避免可变状态,不使用长期运行的状态机。状态从数据库中拉出、使用再写回数据库。这样做的好处是,开发人员不需要操心线程和锁。
  • 22台Redis服务器,每台的都有8-32个实例,因此线上同时使用了100多个Redis实例。
    • Redis主要用于Dashboard通知的后端存储。
    • 所谓通知就是指某个用户like了某篇文章这样的事件。通知会在用户的Dashboard中显示,告诉他其他用户对其内容做了哪些操作。
    • 高写入率使MySQL无法应对。
    • 通知转瞬即逝,所以即使遗漏也不会有严重问题,因此Redis是这一场景的合适选择。
    • 这也给了开发团队了解Redis的机会。
    • 使用中完全没有发现Redis有任何问题,社区也非常棒。
    • 开发了一个基于Scala Futures的Redis接口,该功能现在已经并入了Cell架构。
    • 短地址生成程序使用Redis作为一级Cache,HBase作为永久存储。
    • Dashboard的二级索引是以Redis为基础开发的。
    • Redis还用作Gearman的持久存储层,使用Finagle开发的memcache代理。
    • 正在缓慢地从memcache转向Redis。希望最终只用一个cache服务。性能上Redis与memcache相当。

内部通讯管道(Firehose)

  • 内部的应用需要活跃的信息流通道。这些信息包括用户创建/删除的信息,liking/unliking 的提示,等等。挑战在于这些数据要实时的分布式处理。我们希望能够检测内部运行状况,应用的生态系统能够可靠的生长,同时还需要建设分布式系统的控制中心。
  • 以前,这些信息是基于 Scribe (Facebook 开源的分布式日志系统。)/Hadoop 的分布式系统。服务会先记录在 Scribe 中,并持续的长尾形式写入,然后将数据输送给应用。这种模式可以立即停止伸缩,尤其在峰值时每秒要创建数以千计的信息。不要指望人们会细水长流式的发布文 件和 grep。
  • 内部的 firehose 就像装载着信息的大巴,各种服务和应用通过 Thrift 与消防管线沟通。(一个可伸缩的跨语言的服务开发框架。)
  • LinkedIn 的 Kafka 用于存储信息。内部人员通过 HTTP 链接 firehose。经常面对巨大的数据冲击,采用 MySQL 显然不是一个好主意,分区实施越来越普遍。
  • firehose 的模型是非常灵活的,而不像 Twitter 的 firehose 那样数据被假定是丢失的。
    • firehose 的信息流可以及时的回放。他保留一周内的数据,可以调出这期间任何时间点的数据。
    • 支持多个客户端连接,而且不会看到重复的数据。每个客户端有一个 ID。Kafka 支持客户群,每个群中的客户都用同一个 ID,他们不会读取重复的数据。可以创建多个客户端使用同一个 ID,而且不会看到重复的数据。这将保证数据的独立性和并行处理。Kafka 使用 ZooKeeper (Apache 推出的开源分布式应用程序协调服务。)定期检查用户阅读了多少。

为 Dashboard 收件箱设计的 Cell 架构

  • 现在支持 Dashboard 的功能的分散-集中架构非常受限,这种状况不会持续很久。
    • 解决方法是采用基于 Cell 架构的收件箱模型,与 Facebook Messages 非常相似。
    • 收件箱与分散-集中架构是对立的。每一位用户的 dashboard 都是由其追随者的发言和行动组成的,并按照时间顺序存储。
    • 就因为是收件箱就解决了分散-集中的问题。你可以会问到底在收件箱中放了些什么,让其如此廉价。这种方式将运行很长时间。
  • 重写 Dashboard 非常困难。数据已经分布,但是用户局部升级产生的数据交换的质量还没有完全搞定。
    • 数据量是非常惊人的。平均每条消息转发给上百个不同的用户,这比 Facebook 面对的困难还要大。大数据+高分布率+多个数据中心。
    • 每秒钟上百万次写入,5万次读取。没有重复和压缩的数据增长为2.7TB,每秒百万次写入操作来自 24 字节行键。
    • 已经流行的应用按此方法运行。
  • Cell构架
    • 每个 cell 是独立的,并保存着一定数量用户的全部数据。在用户的 Dashboard 中显示的所有数据也在这个 cell 中。
    • 用户映射到 cell。一个数据中心有很多 cell。
    • 每个 cell 都有一个 HBase 的集群,服务集群,Redis 的缓存集群。
    • 用户归属到 cell,所有 cell 的共同为用户发言提供支持。
    • 每个 cell 都基于 Finagle(Twitter 推出的异步的远程过程调用库),建设在 HBase 上,Thrift 用于开发与 firehose 和各种请求与数据库的链接。
    • 一个用户进入 Dashboard,其追随者归属到特定的 cell,这个服务节点通过 HBase 读取他们的 dashboard 并返回数据。
    • 后台将追随者的 dashboard 归入当前用户的 table,并处理请求。
    • Redis 的缓存层用于 cell 内部处理用户发言。
  • 请求流:用户发布消息,消息将被写入 firehose,所有的 cell 处理这条消息并把发言文本写入数据库,cell 查找是否所有发布消息追随者都在本 cell 内,如果是的话,所有追随者的收件箱将更新用户的 ID。
  • cell 构架的优点:
    • 大规模的请求被并行处理,组件相互隔离不会产生干扰。 cell 是一个并行的单位,因此可以任意调整规格以适应用户群的增长。
    • cell 的故障是独立的。一个 Cell 的故障不会影响其他 cell。
    • cell 的表现非常好,能够进行各种升级测试,实施滚动升级,并测试不同版本的软件。
  • 关键的思想是容易遗漏的:所有的发言都是可以复制到所有的 cell。
    • 每个 cell 中存储的所有发言的单一副本。 每个 cell 可以完全满足 Dashboard 呈现请求。应用不用请求所有发言者的 ID,只需要请求那些用户的 ID。他可以在 dashboard 返回内容。每一个 cell 都可以满足 Dashboard 的所有需求,而不需要与其他 cell 进行通信。
    • 用到两个 HBase table :一个 table 用于存储每个发言的副本,这个 table 相对较小。在 cell 内,这些数据将与存储每一个发言者 ID。第二个 table 告诉我们用户的 dashboard 不需要显示所有的追随者。当用户通过不同的终端访问一个发言,并不代表阅读了两次。收件箱模型可以保证你阅读到。
    • 发言并不会直接进入到收件箱,因为那实在太大了。所以,发言者的 ID 将被发送到收件箱,同时发言内容将进入 cell。这个模式有效的减少了存储需求,只需要返回用户在收件箱中浏览发言的时间。而缺点是每一个 cell 保存所有的发言副本。令人惊奇的是,所有发言比收件箱中的镜像要小。每天每个 cell 的发言增长 50GB,收件箱每天增长2.7TB。用户消耗的资源远远超过他们制造的。
    • 用户的 dashboard 不包含发言的内容,只显示发言者的 ID,主要的增长来自 ID。
    • 当追随者改变时,这种设计方案也是安全的。因为所有的发言都保存在 cell 中了。如果只有追随者的发言保存在 cell 中,那么当追随者改变了,将需要一些回填工作。
    • 另外一种设计方案是采用独立的发言存储集群。这种设计的缺点是,如果群集出现故障,它会影响整个网站。因此,使用 cell 的设计以及后复制到所有 cell 的方式,创建了一个非常强大的架构。
  • 一个用户拥有上百万的追随者,这带来非常大的困难,有选择的处理用户的追随者以及他们的存取模式(见Feeding Frenzy
    • 不同的用户采用不同并且恰当的存取模式和分布模型,两个不同的分布模式包括:一个适合受欢迎的用户,一个使用大众。
    • 依据用户的类型采用不同的数据处理方式,活跃用户的发言并不会被真正发布,发言将被有选择的体现。
    • 追随了上百万用户的用户,将像拥有上百万追随者的用户那样对待。
  • cell 的大小非常难于决定。cell 的大小直接影响网站的成败。每个 cell 归于的用户数量是影响力之一。需要权衡接受怎样的用户体验,以及为之付出多少投资。
  • 从 firehose 中读取数据将是对网络最大的考验。在 cell 内部网络流量是可管理的。
  • 当更多 cell 被增添到网络中来,他们可以进入到 cell 组中,并从 firehose 中读取数据。一个分层的数据复制计划。这可以帮助迁移到多个数据中心。

最新评论

我也要发表评论


返回顶部

分享到微信

打开微信,点击顶部的“╋”,
使用“扫一扫”将网页分享至微信。