# Tumblr Architecture-150 亿页面浏览量一个月，比 Twitter 更难扩展

> 原文： [http://highscalability.com/blog/2012/2/13/tumblr-architecture-15-billion-page-views-a-month-and-harder.html](http://highscalability.com/blog/2012/2/13/tumblr-architecture-15-billion-page-views-a-month-and-harder.html)

![](img/3f4661baa53cbc9eae481b3c2ce15bb3.png)

Tumblr 每月拥有超过 150 亿的页面浏览量，已成为一个非常流行的博客平台。 用户可能会喜欢 Tumblr 的简单性，美观性，对用户体验的高度关注或友好而参与的社区，但他们喜欢。

每月以 30％以上的速度增长并非没有挑战。 其中一些可靠性问题。 它有助于认识到 Tumblr 的运行规模惊人地惊人：每天有 5 亿次页面浏览，每秒约有 4 万个请求的峰值速率，每天约有 3TB 的新数据存储，所有这些都在 1000 多个服务器上运行。

成功创业公司的常见模式之一是从创业公司到疯狂成功创业的危险鸿沟。 寻找人员，不断发展的基础架构，为旧的基础架构提供服务，同时处理每月逐月的巨大流量增长（全都只有四名工程师），这意味着您必须对工作内容做出艰难的选择。 这就是 Tumblr 的情况。 现在，拥有 20 名工程师，他们有足够的精力来解决问题并开发一些非常有趣的解决方案。

Tumblr 开始时是一种非常典型的大型 LAMP 应用程序。 他们现在的发展方向是朝着围绕 Scala，HBase，Redis，Kafka，Finagle 构建的分布式服务模型以及为仪表板提供动力的有趣的基于单元的体系结构。 现在，我们正在努力解决其 PHP 应用程序中的短期问题，将其撤出并使用服务来正确完成。

Tumblr 的主题是大规模过渡。 从 LAMP 堆栈过渡到有点出血的边缘堆栈。 从小型启动团队过渡到配备齐全的现成开发团队，以开发新功能和基础架构。 为了帮助我们理解 Tumblr 的生活方式，Tumblr 的分布式系统工程师，资深的初学者 [Blake Matheny](http://www.linkedin.com/in/bmatheny) 。 布雷克（Blake）对 Tumblr 之家的评价如下：

网站： [http://www.tumblr.com/](http://www.tumblr.com/)

## 统计信息

*   每天有 5 亿页面浏览量
*   每月浏览量超过 15B
*   〜20 名工程师
*   每秒约 40k 请求的峰值速率
*   每天有 1 TB 以上的数据进入 Hadoop 集群
*   每天有许多 TB 进入 MySQL / HBase / Redis / Memcache
*   以每月 30％的速度增长
*   正在生产的〜1000 个硬件节点
*   每个工程师每月有数十亿的页面访问
*   帖子每天大约 50GB。 关注者列表每天更新约 2.7TB。
*   仪表板每秒运行一百万次写入，每秒 50K 读取，并且还在不断增长。

## 软件

*   OS X 用于开发，Linux（CentOS，科学版）投入生产
*   Apache
*   PHP，Scala，Ruby
*   Redis，HBase，MySQL
*   Varnish，HA 代理，nginx，
*   Memcache，Gearman，Kafka， Kestrel，Finagle
*   节俭，HTTP
*   [Func](http://func.et.redhat.com/) -安全，可编写脚本的远程控制框架和 API
*   Git，Capistrano，木偶，詹金斯

## 硬件

*   500 台 Web 服务器
*   200 个数据库服务器（其中许多是我们因故障而从备用池中抽出的一部分）
    *   47 个池
    *   30 个碎片
*   30 个内存缓存服务器
*   22 个 Redis 服务器
*   15 个清漆服务器
*   25 个代理节点
*   8 nginx
*   14 个作业队列服务器（红 est + Gearman）

## 架构

*   Tumblr 具有与其他社交网络不同的使用模式。
    *   每天有 50+百万个帖子，平均帖子数达数百人。 拥有数百万关注者的不仅仅是一两个用户。 Tumblr 用户的图表有数百个关注者。 这与任何其他社交网络都不同，这就是使 Tumblr 如此难以扩展的原因。
    *   在用户花费的时间方面排名第二。 内容很吸引人。 它是图片和视频。 帖子没有字节大小。 它们并不都是长格式，但是它们有能力。 人们会写一些值得一读的深入内容，因此人们会呆上几个小时。
    *   用户与其他用户建立连接，因此他们将数百页返回到仪表板以读取内容。 其他社交网络只是您采样的流。
    *   的含义是，鉴于用户数量，用户的平均覆盖范围以及用户的高发布活动，需要处理大量更新。
*   Tumblr 在一个托管站点中运行。 设计在将来会考虑地理分布。
*   以 Tumblr 为平台的两个组件：公共 [Tumblelogs](http://www.tumblr.com/tagged/tumblelogs) 和 [信息显示板](http://www.tumblr.com/tagged/tumblr+dashboard)
    *   公众 Tumblelog 是公众根据博客处理的内容。 易于缓存，因为它不是那么动态。
    *   仪表板类似于 Twitter 时间线。 用户从他们关注的所有用户那里获取实时更新。
        *   与博客的缩放特性非常不同。 缓存并不是那么有用，因为每个请求都是不同的，尤其是对于活跃的关注者而言。
        *   需要实时且一致。 不应显示过时的数据。 而且有很多数据要处理。 帖子每天只有大约 50GB。 关注者列表每天更新 2.7TB。 媒体全部存储在 S3 中。
    *   大多数用户都将 Tumblr 用作消费内容的工具。 每天的 500+百万页面浏览量中，有 70％用于仪表板。
    *   仪表板的可用性非常好。 Tumblelog 表现不佳，因为它们具有难以迁移的旧式基础架构。 与一个小团队一起，他们必须选择并解决扩展问题。

### 旧 Tumblr

*   当公司开始使用 Rackspace 时，它给每个自定义域博客一个 A 记录。 当他们超过 Rackspace 时，太多的用户无法迁移。 这是 2007 年。他们在 Rackspace 上仍具有自定义域。 他们使用 HAProxy 和 Varnish 将 Rackspace 路由回到其 colo 空间。 这样的遗留问题很多。
*   传统的 LAMP 进展。
    *   历史上是用 PHP 开发的。 几乎每个工程师都使用 PHP 进行编程。
    *   从 Web 服务器，数据库服务器和 PHP 应用程序开始，然后开始发展。
    *   要扩展规模，他们开始使用内存缓存，然后放入前端缓存，然后在缓存之前放入 HAProxy，然后使用 MySQL 分片。 MySQL 分片非常有用。
    *   充分利用单个服务器的方法。 在过去的一年中，他们在 C 语言中开发了一些后端服务： [ID 生成器](http://engineering.tumblr.com/post/10996371189/blake-matheny-id-generation-at-scale) 和 [楼梯](http://engineering.tumblr.com/post/7819252942/staircar-redis-powered-notifications) ，使用 Redis 为仪表板通知供电
*   仪表板使用分散收集方法。 当用户访问其仪表板时，将显示事件。 将拉出并显示您关注的用户的事件。 这将再扩展 6 个月。 由于数据是按时间排序的分片方案，因此效果不佳。

### 新 Tumblr

*   由于招聘和开发速度原因，已更改为以 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.js 开发不够完善，无法提供标准和最佳实践以及大量经过测试的代码。 使用 Scala，您可以使用所有 Java 代码。 关于如何以可扩展的方式使用它的知识并不多，它们的目标是 5 毫秒的响应时间，4 个 9s HA，每秒 40K 个请求，还有一些每秒 40 万个请求。 他们可以利用 Java 生态系统中的很多功能。
*   内部服务正在从基于 C / libevent 的状态转变为基于 Scala / Finagle 的状态。
*   正在使用更新的非关系数据存储，例如 HBase 和 Redis，但它们的大部分数据当前存储在高度分区的 MySQL 体系结构中。 不使用 HBase 替换 MySQL。
*   HBase 支持数十亿个 URL 以及所有历史数据和分析的 URL 缩写。 一直坚如磐石。 HBase 用于具有较高写入要求的情况，例如替换仪表板每秒写入一百万次。 未部署 HBase 而不是部署 MySQL，因为他们无法与他们所拥有的人押宝 HBase 上的业务，因此他们开始将其用于规模较小，不太关键的项目中以获取经验。
*   MySQL 和时间序列数据分片的问题一直是一个热点。 由于从属服务器上的插入并发性，还遇到了读取复制滞后的问题。
*   创建了一个公共服务框架。
    *   花了很多时间来预先解决如何管理分布式系统的操作问题。
    *   建造了一种 Rails 脚手架，但用于服务。 模板用于在内部引导服务。
    *   从操作角度来看，所有服务看起来都是相同的。 检查统计信息，监视，启动和停止所有服务的工作方式相同。
    *   工具是围绕 [SBT](https://github.com/harrah/xsbt/wiki) （一种 Scala 生成工具）的构建过程使用的，它使用插件和帮助程序来处理一些常见的活动，例如在其中标记内容 git，发布到存储库等。大多数开发人员不必进入构建系统的胆量。
*   前端层使用 HAProxy。 Varnish 可能会受到公共博客的欢迎。 40 台机器。
*   500 个运行 Apache 的 Web 服务器及其 PHP 应用程序。
*   200 个数据库服务器。 使用许多数据库服务器是出于高可用性的原因。 使用了商品硬件，MTBF 令人惊讶地低。 丢失的硬件比预期的要多得多，因此在发生故障的情况下有许多备用件。
*   6 个支持 PHP 应用程序的后端服务。 一个团队致力于开发后端服务。 每 2-3 周推出一项新服务。 包括仪表板通知，仪表板二级索引，URL 缩短器和用于处理透明分片的内存缓存代理。
*   在 [MySQL 分片](http://assets.en.oreilly.com/1/event/74/Massively%20Sharded%20MySQL%20at%20Tumblr%20Presentation.pdf) 中投入了大量时间和精力。 尽管 MongoDB 在纽约（其所在地）很受欢迎，但并未使用。 MySQL 可以很好地扩展。.
*   Gearman 是一种工作队列系统，用于长时间的开火和忘却式工作。
*   可用性是根据覆盖范围衡量的。 用户可以访问自定义域或仪表板吗？ 同样在错误率方面。
*   历史上最高优先项是固定的。 现在，对故障模式进行了系统地分析和处理。 目的是从用户角度和应用程序角度衡量成功。 如果无法满足要求的一部分，则为
*   最初，Actor 模型与 Finagle 一起使用，但已被删除。 为了免于失火，使用作业队列。 此外，Twitter 的 [实用程序库](http://twitter.github.com/util/util-core/target/site/doc/main/api/com/twitter/util/package.html) 包含 [期货](http://twitter.github.com/util/util-core/target/site/doc/main/api/com/twitter/util/package.html) 实现和服务 就期货而言。 在需要线程池的情况下，将期货传递到期货池中。 一切都提交给将来的池以异步执行。
*   Scala 鼓励没有共享状态。 Finagle 被认为是正确的，因为它已经在 Twitter 上进行了生产测试。 使用 Scala 或 Finagle 中的构造避免了可变状态。 不再使用长时间运行的状态机。 状态从数据库中拉出，使用，然后写回数据库。 优势在于，开发人员无需担心线程或锁。
*   22 个 Redis 服务器。 每个服务器有 8-32 个实例，因此生产中使用了 100 个 Redis 实例。
    *   用于仪表板通知的后端存储。
    *   通知就像用户喜欢您的信息一样。 通知会显示在用户的仪表板上，以指示其他用户对其内容执行的操作。
    *   高写入率使 MySQL 不适合使用。
    *   通知是短暂的，因此删除通知不会太可怕，因此 Redis 是此功能的可接受选择。
    *   让他们有机会了解 Redis 并熟悉它的工作原理。
    *   Redis 完全没有问题，社区很棒。
    *   为 Redis 创建了一个基于 Scala 期货的界面。 现在，此功能正在迁移到其单元架构中。
    *   URL 缩短器使用 Redis 作为第一级缓存，使用 HBase 作为永久存储。
    *   信息中心的二级索引围绕 Redis 构建。
    *   使用由 Finagle 构建的内存缓存代理，Redis 用作 Gearman 的持久层。
    *   从 Memcache 缓慢移至 Redis。 最终希望仅依靠一种缓存服务。 性能与 Memcache 相当。

### 内部消防水带

*   内部应用程序需要访问活动流。 活动流是有关用户创建/删除帖子，喜欢/取消喜欢帖子等的信息。一个挑战是实时分发如此多的数据。 希望能够在内部进行扩展并且可以可靠地扩展应用程序生态系统。 需要一个中心分发点。
*   以前，此信息是使用 Scribe / Hadoop 分发的。 服务将登录到 Scribe 中并开始拖尾，然后将该数据通过管道传输到应用程序中。 此模型几乎立即停止了扩展，特别是在人们每秒创建数千个帖子的高峰期。 不想让人们将文件和管道拖到 grep。
*   创建了一个内部 firehose 作为消息总线。 服务和应用程序通过 Thrift 与 Firehose 对话。
*   LinkedIn 的 Kafka 用于存储邮件。 在内部，消费者使用 HTTP 流从 Firehose 读取数据。 未使用 MySQL 是因为分片实现经常更改，因此使用巨大的数据流来实现它不是一个好主意。
*   firehose 模型非常灵活，与假定数据丢失的 Twitter firehose 不同。
    *   消防水带可以及时退绕。 它保留一周的数据。 在连接时，可以指定开始阅读的时间点。
    *   多个客户端可以连接，并且每个客户端都不会看到重复的数据。 每个客户端都有一个客户端 ID。 卡夫卡支持一个消费者群体的想法。 消费者组中的每个消费者都有自己的消息，不会看到重复的消息。 可以使用相同的使用者 ID 创建多个客户，并且客户不会看到重复的数据。 这样就可以独立并并行地处理数据。 Kafka 使用 ZooKeeper 定期检查消费者阅读的距离。

### 仪表板收件箱的单元格设计

*   当前用于提供仪表板功能的分散收集模型的跑道非常有限。 它不会持续更长的时间。
    *   解决方案是移至使用类似于 [Facebook 消息](http://www.facebook.com/note.php?note_id=454991608919) 的基于单元的架构实现的收件箱模型。
    *   收件箱与分散收集相反。 用户的仪表板由跟随的用户的帖子和其他用户采取的操作组成，按时间顺序逻辑存储在一起。
    *   解决了分散收集问题，因为它是一个收件箱。 您只需要问收件箱中的内容，就可以节省费用，然后便宜得多。 这将扩展很长时间。
*   很难重写仪表板。 数据具有分布式性质，但具有交易质量，用户无法部分获得更新。
    *   数据量令人难以置信。 消息必须平均发送给数百个不同的用户，这与 Facebook 面临的问题截然不同。 大日期+高分发率+多个数据中心。
    *   规格为每秒写一百万，每秒读 50K。 数据集大小为 2.7TB 的数据增长，未启用任何复制或压缩。 百万写秒是从 24 字节行键写入的，它指示收件箱中的内容。
    *   在已经流行的必须保持运行的应用程序上执行此操作。
*   细胞
    *   单元是一个独立的安装，其中包含适用于一系列用户的所有数据。 呈现用户仪表板所需的所有数据都在单元格中。
    *   用户被映射到单元格中。 每个数据中心存在许多单元。
    *   每个单元都有一个 HBase 群集，服务群集和 Redis 缓存群集。
    *   用户被安置在一个单元中，并且所有单元都通过 firehose 更新消耗所有帖子。
    *   每个单元都基于 Finagle，并通过 Thrift 上的 firehose 和服务请求填充 HBase。
    *   用户进入仪表板，用户位于某个特定的单元格内，服务节点通过 HBase 读取其仪表板，并将数据传回。
    *   后台任务从防火墙中消耗掉，以填充表和处理请求。
    *   Redis 缓存层用于单元内的帖子。
*   请求流：用户发布帖子，该帖子被写入 firehose，所有单元格消耗该帖子并将该帖子内容写到帖子数据库中，单元格查找以查看帖子创建者是否有任何关注者 在单元格中，如果是的话，则跟随者收件箱将更新为帖子 ID。
*   电池设计的优势：
    *   大规模规模需要并行化，而并行化要求组件彼此隔离，因此没有相互作用。 单元提供一个并行化单元，可以随着用户群的增长而调整为任意大小。
    *   细胞隔离故障。 一个单元故障不会影响其他单元。
    *   单元可以实现一些不错的功能，例如测试升级，实施滚动升级以及测试软件的不同版本的能力。
*   容易遗漏的关键思想是： 所有帖子都复制到所有单元格 。
    *   每个单元格都存储所有帖子的单个副本。 每个单元格可以完全满足仪表板渲染请求。 应用程序不要求提供所有帖子 ID，然后要求提供这些 ID 的帖子。 它可以为用户返回仪表板内容。 每个单元都具有完成仪表板请求所需的所有数据，而无需进行任何跨单元通信。
    *   使用了两个 HBase 表：一个存储每个帖子的副本。 与存储该单元内每个用户的每个帖子 ID 的另一个表相比，该数据很小。 第二张表告诉用户仪表板的外观，这意味着他们不必获取用户关注的所有用户。 这也意味着跨客户，他们将知道您是否阅读了帖子，并且在其他设备上查看帖子并不意味着您阅读了相同的内容两次。 使用收件箱模型，状态可以保持在您已阅读的内容上。
    *   帖子太大，因此无法直接放入收件箱。 因此，将 ID 放入收件箱，并将帖子内容仅放入单元格一次。 该模型大大减少了所需的存储空间，同时使返回用户收件箱的按时间顺序的视图变得简单。 缺点是每个单元格包含完整的呼叫记录副本。 令人惊讶的是，帖子比收件箱映射要小。 每天的后期增长是每个单元 50GB，收件箱每天增长 2.7TB。 用户消费超过他们生产的东西。
    *   用户的信息中心不包含帖子的文本，仅包含帖子的 ID，而大部分增长都来自 ID。
    *   随着关注者的更改，设计是安全的，因为所有帖子均已在单元格中。 如果只有关注者帖子存储在一个单元格中，那么随着关注者的更改，该单元格将过时，并且需要某种回填过程。
    *   替代设计是使用单独的帖子群集来存储帖子文本。 这种设计的缺点是，如果群集出现故障，则会影响整个站点。 使用单元设计并向所有单元复制后，将创建一个非常强大的体系结构。
*   拥有数百万个真正活跃的关注者的用户可以通过根据其访问模型选择性地实现用户供稿来处理（请参见 [Feeding Frenzy](http://highscalability.com/blog/2012/1/17/paper-feeding-frenzy-selectively-materializing-users-event-f.html) ）。
    *   不同的用户具有适当的不同访问模型和分发模型。 两种不同的分发模式：一种用于流行用户，另一种用于其他人。
    *   数据的处理方式取决于用户类型。 来自活跃用户的帖子实际上不会发布，而帖子将有选择地实现。
    *   关注数百万用户的用户与拥有数百万关注者的用户类似。
*   单元大小难以确定。 单元的大小是故障的影响点。 影响到一个单元的用户数量。 要权衡他们愿意接受的用户体验以及相应的费用。
*   从 firehose 读取是最大的网络问题。 在一个小区内，网络流量是可管理的。
*   随着添加更多的细胞，可以将细胞放入一个从火喉读取的细胞组中，然后复制到该组中的所有细胞中。 分层复制方案。 这也将有助于转移到多个数据中心。

### 关于在纽约创业

*   NY 是一个不同的环境。 很多财务和广告。 招聘具有挑战性，因为没有太多的启动经验。
*   在过去的几年中，NY 致力于帮助初创企业。 纽约大学和哥伦比亚大学推出的计划旨在使学生在初创企业中获得有趣的实习机会，而不仅仅是去华尔街。 彭博市长正在建立一个专注于技术的本地校园。

### 团队结构

*   团队：基础架构，平台，SRE，产品，网络运营，服务。
*   基础结构：第 5 层及以下。 IP 地址及以下，DNS，硬件配置。
*   平台：核心应用程序开发，SQL 分片，服务，Web 操作。
*   SRE：位于服务团队和网络运营团队之间。 在可靠性和可伸缩性方面专注于更迫切的需求。
*   服务团队：专注于更具战略意义的工作（一个月或两个月）。
*   Web 操作：负责问题检测和响应以及调整。

### 软件部署

*   从一组 rsync 脚本开始，这些脚本将 PHP 应用程序分布在各处。 一旦计算机数量达到 200，系统就开始出现问题，部署需要很长时间才能完成，并且计算机将处于部署过程的各种状态。
*   下一阶段使用 Capistrano 将部署过程（开发，登台，生产）构建到其服务堆栈中。 可以在数十台计算机上使用服务，但是通过 SSH 连接后，在部署到数百台计算机上时再次开始出现故障。
*   现在，所有计算机上都运行一个协调软件。 基于 RedHat 的 Func，这是一种用于向主机发出命令的轻量级 API。 缩放内置于 Func 中。
*   通过在一组主机上执行 X 来在 Func 上进行构建部署，这避免了 SSH。 假设您要在组 A 上部署软件。主服务器伸向一组节点并运行 deploy 命令。
*   deploy 命令通过 Capistrano 实现。 它可以进行 git checkout 或从存储库中提取。 易于扩展，因为他们正在使用 HTTP。 他们喜欢 Capistrano，因为 Capistrano 支持基于简单目录的版本控制，该版本与他们的 PHP 应用程序很好地兼容。 向版本更新迈进，每个目录包含一个 [SHA](http://book.git-scm.com/1_the_git_object_model.html) ，因此可以轻松检查版本是否正确。
*   Func API 用于报告状态，即这些机器具有这些软件版本。
*   可以安全地重新启动其所有服务，因为它们会清空连接，然后重新启动。
*   激活之前，所有功能均在暗模式下运行。

### 开发

*   从这样的哲学开始：任何人都可以使用他们想要的任何工具，但是随着团队的成长，这种想法不起作用了。 新员工的入职非常困难，因此他们已经在堆栈上进行了标准化，以便他们能与之相处，快速发展团队，更快地解决生产问题并围绕他们开展业务。
*   流程大致类似于 Scrum。 轻巧。
*   每个开发人员都有一个预先配置的开发计算机。 它通过 Puppet 获取更新。
*   开发人员机器可以滚动更改，进行测试，然后将其部署到阶段，然后将其部署到生产中。
*   开发人员使用 vim 和 Textmate。
*   测试是通过 PHP 应用程序的代码审查进行的。
*   在服务方面，他们已经实现了具有提交挂钩，Jenkins 以及持续集成和构建通知的测试基础架构。

### 招聘流程

*   面试通常避免数学，困惑和脑筋急转弯。 试着针对候选人实际要做的工作提出问题。 他们聪明吗？ 他们会把事情做好吗？ 但是衡量“完成工作”的难度很难评估。 目标是找到优秀的人才，而不是将人才拒之门外。
*   专注于编码。 他们会要求提供示例代码。 在电话采访中，他们将使用 Collabedit 编写共享代码。
*   面试不是对抗性的，他们只是想找到最好的人。 面试期间，候选人可以使用他们的所有工具，例如 Google。 他们的想法是，开发人员在拥有工具时才能发挥最大作用，这就是他们进行采访的方式。
*   挑战是找到在 Tumblr 的流量水平下具有所需扩展经验的人员。 世界上很少有公司致力于解决他们所面临的问题。
    *   例如，对于一个新的 ID 生成器，他们需要一个 JVM 进程以小于 1ms 的速率生成服务响应，速率为每秒 10K 请求和 500 MB RAM 限制并具有高可用性。 他们发现串行收集器在此特定工作负载下的延迟最小。 在 JVM 调整上花费了很多时间。
*   在 Tumblr 工程博客上，他们张贴了悼念词，表达对 [Dennis Ritchie](http://engineering.tumblr.com/post/11381547149/derekg-rip-dennis-ritchie-he-gave-us-such) & [[ John McCarthy](http://engineering.tumblr.com/post/11893095969/john-mccarthy-widely-considered-the-father-of) 。 这是一种怪异的文化。

## 获得的经验教训

*   到处都是自动化。
*   MySQL（加上分片）可扩展，而应用则不能。
*   Redis 很棒。
*   Scala 应用程序表现出色。
*   当您不确定项目是否可行时，请报废项目。
*   请勿通过无用的技术手腕来依靠他们的生存来雇用人员。 雇用他们是因为他们适合您的团队并且可以胜任。
*   选择一个可以帮助您招聘所需人员的堆栈。
*   建立团队的能力。
*   阅读论文和博客文章。 像电池体系结构和选择性实现这样的关键设计思想都来自其他地方。
*   询问您的同龄人。 他们与来自 Facebook，Twitter，LinkedIn 的工程师进行了交流，并交流了经验。 您可能没有权限访问此级别，但可以与某人联系。
*   韦德，不要涉足技术领域。 他们在尝试将 HBase 和 Redis 投入生产之前，通过在试点项目或损害程度可能有限的角色中使用它们来学习。

非常感谢 Blake 的采访。 他对时间很宽容，对解释也很耐心。 如果您想谈谈您的架构配置文件，请 [与我联系](http://highscalability.com/contact/) 。

## 相关文章

*   [Tumblr Engineering Blog](http://engineering.tumblr.com/) -包含很多优秀文章
*   [与 Nathan Hamblen 一起使用 Finagle 和 Ostrich 构建网络服务](http://vimeo.com/29763331) -Finagle 很棒
*   [鸵鸟](https://github.com/twitter/ostrich/) -Scala 服务器的统计收集器&报告程序
*   [规模为](http://tumblr.mobocracy.net/post/10984130543/id-generation-at-scale) 的 ID 生成，作者 Blake Matheny
*   [Finagle](http://twitter.github.com/finagle/) -JVM 的网络堆栈，可用于构建 Java，Scala 或任何 JVM 托管语言的异步远程过程调用（RPC）客户端和服务器 。 Finagle 提供了一组丰富的独立于协议的工具。
*   [来自 Tumblr 的 Finagle Redis 客户端](https://github.com/twitter/finagle/commit/c30ba58acfc19b96807f72162dcdd913365e2de2)
*   [Tumblr。 Evan Elias 撰写的大量分片的 MySQL](http://assets.en.oreilly.com/1/event/74/Massively%20Sharded%20MySQL%20at%20Tumblr%20Presentation.pdf) -关于 MySQL 分片的更好的演示之一
*   [Staircar：由 Redis 驱动的通知](http://engineering.tumblr.com/post/7819252942/staircar-redis-powered-notifications) ，作者：布莱克·马森尼（Blake Matheny）
*   [Flickr 架构](http://highscalability.com/flickr-architecture)-谈论 Flickr 的单元架构

是否有关于此基于单元的体系结构的更多信息？ 这些关键字对于 Google 来说是非常通用的...

如果您还要存储数百万个非法 mp3，也很难扩展。
查看 ex.fm API 关于 Tumblr 作为侵犯版权的避风港所暴露的内容。 在音乐方面，它们比 megaupload 更糟糕

我不知道该体系结构是否有一个标准术语 Andrew。 Salesforce 做类似的事情，例如使用术语 Pod。 Flickr 称之为联合方法。

似乎大多数服务器都包含：

500 台运行 Apache 及其 PHP 应用程序的 Web 服务器。

使用 Nginx / PHP-FPM 代替 Apache / mod_php 是否有意义，因为事实证明，这可以显着提高并发请求和服务整个页面的时间？

您为什么选择 CentOS / Scientific 而不是 RHEL？

> 最初，Finagle 使用了 Actor 模型，但该模型已被删除。

Anywhere I can read up on the issues they had with this approach?

@meh：RHES 会带来什么好处？ 这将是相当标准的安装映像/配置。 任何操作系统问题，重新安装都很简单（为什么要进行故障排除，当您可以使用 PXE + config 管理在< 10m 中重新创建时）。 如此规模的 RHES 似乎是一笔不菲的巨额支出。

关于 tumblr 内部技术的真棒读物。 感谢您发布文章，这一点非常有用。

虚拟化呢？ 他们仅使用硬件服务器吗？

管理所有这些的成本必须是巨大的。 该公司得到了风险投资公司的支持，但我想知道他们为保持运营状况每年亏损多少钱？

> 是否有关于此基于单元的体系结构的更多信息？ 这些关键字对于 Google 来说是非常通用的...

还可以在该网站上查看 Evernote 上的文章； 它们具有类似的“单元”架构。

马特，感谢您提供有关 Evernote 的提示。 我看了一下这篇文章：http://highscalability.com/blog/2011/5/23/evernote-architecture-9-million-users-and-150million-reques.html，假设它是您本人 在想什么？

我真的希望有人可以链接到受访者提到的实际论文。

关于可伸缩性的噪音太多了，即使在这个级别上，也确实没有那么困难。

本文所显示的所有内容是，您可以拥有一个真正糟糕的体系结构，并且仍然维持相当大的流量。

这篇文章说

> MySQL（加上分片）可扩展，而应用则不能。

在多个地方，但是 MySQL 没有分片。 这不是 MySQL 的功能，永远不会。

应用程序在将数据发送到 MySQL 之前先对其进行分区。 这要求应用程序（或应用程序层）完全了解分区并进行管理。 这样，您现在已经删除了 RDBMS 的大多数核心功能（联接，事务，外键完整性）。 这就引出了一个问题，当我们在追求扩展到所需容量的过程中，已经中止了 SQL 的所有基本功能时，为什么要全部使用 SQL。

是的，可以使用 MySQL 技术来执行此操作，但是最终您不再像 RDMBS 那样使用它。 它具有您无法使用的所有功能，现在严重依赖于应用程序。 似乎仅仅使用为这种操作而设计的数据库并从头开始扩展会更聪明。

@本·乌雷茨基

使用 nginx / php-cgi 的性能更高，但是您必须注意：
-您的脚本必须绝对无锁且响应迅速。 一个“较长的”执行时间脚本（但< 1s）可能会阻止一个 CGI 进程，这对于整个服务器来说应该是不完整的。
-您需要找到一个“完美”的 php 版本，因为一个进程将执行的请求比使用 apache 重新发出的请求要多。 对于某些版本，您可能会感到有些意外。

根据我自己的经验，在（nginx）/ fastcgi 上具有良好的可靠性需要花费更多时间。

架构...对...根本不起作用的功能呢，例如...搜索！ 还是不存在...像在主题开发人员的情况下清理上传的资源？

附言 不要误会我的意思-我喜欢 Tumblr 的简单性，但有些事情确实会踩到您的脚趾...

令人印象深刻的是，只有 15 位以上的网页浏览工程师才 20 名。 令人印象深刻。

根据文章 HBASE 的使用：
支持 URL 缩短，
存储历史数据和分析
仪表板替换
我希望这意味着，所有博客 URL，博客数据都存储在 HBASE 中。 如果我错了，请纠正我。

文章还说，
大量数据存储在 MySQL 中。

那么 MySQL 是否用于存储在引入 HBASE 之前创建的旧博客？ 如果是这样，服务节点是否将决定在何处加载仪表板？
如果有人清楚，请解释。

当整个小区停止服务时会发生什么？ 该单元中的用户是否已重新归宿？ 由于所有这些信息都存储在故障节点中，这将如何影响那些用户的收件箱？

“内部服务正在从基于 C / libevent 的方式转变为基于 Scala / Finagle 的方式”

您能描述使用 Scala / Finagle 而不是 C / libevent 的原因吗？
谢谢！

将这样的系统以及支持该系统的业务基础结构整合在一起需要做很多工作。 可能需要花费大量时间进行阅读和编码。 我说，恭喜 Tumblr 和 CEO Karp。 继续做您所做的伟大工作。 :)

本文提到了 Nginx，但没有说明如何使用它。 Varnish 用于缓存，HAProxy 用于 LB，Nginx 呢？

感谢您的发布。 非常全面，连贯，详细。 可以确定的时间是 Verizon 之前的收购。 我想知道老电话公司做了什么来弄乱这个漂亮的沙箱。 另一个奇迹：他们赚钱了吗？