导读:和许多新兴的网站一样,著名的轻博客服务 Tumblr 在急速发展中面临了系统架构的瓶颈。每天 5 亿次浏览量,峰值每秒 4 万次请求,每天 3TB 新的数据存储,超过 1000 台服务器,这样的情况下如何保证老系统平稳运行,平稳过渡到新的系统,Tumblr 正面临巨大的挑战。近日,HighScalability 网站的 Todd Hoff 采访了该公司的分布式系统工程师 Blake Matheny,撰文系统介绍了网站的架构,内容很有价值。我们也非常希望国内的公司和团队多做类似分享,贡献于社区的同时,更能提升自身的江湖地位,对招聘、业务发展都好处多多。
英文原文:High Scalability
Tumblr 每月页面浏览量超过 150 亿次,已经成为火爆的博客社区。用户也许喜欢它的简约、美丽,对用户体验的强烈关注,或是友好而忙碌的沟通方式,总之,它深得人们的喜爱。
每月超过 30% 的增长当然不可能没有挑战,其中可靠性问题尤为艰巨。每天 5 亿次浏览量,峰值每秒 4 万次请求,每天 3TB 新的数据存储,并运行于超过 1000 台服务器上,所有这些帮助 Tumblr 实现巨大的经营规模。
创业公司迈向成功,都要迈过危险的迅速发展期这道门槛。寻找人才,不断改造基础架构,维护旧的架构,同时要面对逐月大增的流量,而且曾经只有 4 位工程师。这意味着必须艰难地选择应该做什么,不该做什么。这就是 Tumblr 的状况。好在现在已经有 20 位工程师了,可以有精力解决问题,并开发一些有意思的解决方案。
Tumblr 最开始是非常典型的 LAMP 应用。目前正在向分布式服务模型演进,该模型基于Scala、HBase、Redis(著名开源K-V存储方案)、Kafka(Apache 项目,出自 LinkedIn 的分布式发布-订阅消息系统)、Finagle(由 Twitter 开源的容错、协议中立的 RPC 系统),此外还有一个有趣的基于 Cell 的架构,用来支持 Dashboard(CSDN 注:Tumblr 富有特色的用户界面,类似于微博的时间轴)。
Tumblr 目前的最大问题是如何改造为一个大规模网站。系统架构正在从 LAMP 演进为最先进的技术组合,同时团队也要从小的创业型发展为全副武装、随时待命的正规开发团队,不断创造出新的功能和基础设施。下面就是 Blake Matheny 对 Tumblr 系统架构情况的介绍。
网站地址
主要数据
软件环境
硬件环境
架构
1. 相对其他社交网站而言,Tumblr 有其独特的使用模式:
2. Tumblr 目前运行在一个托管数据中心中,已在考虑地域上的分布性。
3. Tumblr 作为一个平台,由两个组件构成:公共 Tumblelogs 和 Dashboard
老的架构
Tumblr 最开始是托管在 Rackspace 上的,每个自定义域名的博客都有一个A记录。当 2007 年 Rackspace 无法满足其发展速度不得不迁移时,大量的用户都需要同时迁移。所以他们不得不将自定义域名保留在 Rackspace,然后再使用 HAProxy 和 Varnish 路由到新的数据中心。类似这样的遗留问题很多。
开始的架构演进是典型的 LAMP 路线:
Dashboard 采用了“扩散-收集”方式。当用户访问 Dashboard 时将显示事件,来自所关注的用户的事件是通过拉然后显示的。这样支撑了 6 个月。由于数据是按时间排序的,因此 sharding 模式不太管用。
新的架构
由于招人和开发速度等原因,改为以 JVM 为中心。目标是将一切从 PHP 应用改为服务,使应用变成请求鉴别、呈现等诸多服务之上的薄层。
这其中,非常重要的是选用了 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 上插入并发,也会遇到读复制延迟问题。
此外,还开发了一个公用服务框架:
200台数据库服务器中,很多是为了提高可用性而设,使用的是常规硬件,但 MTBF(平均故障间隔时间)极低。故障时,备用充足。
为了支持 PHP 应用有 6 个后端服务,并有一个小组专门开发后端服务。新服务的发布需要两到三周,包 括 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 实例。
(先到这里吧,敬请期待下篇,包括如何用 Kafaka、Scribe、Thrift 实现内部活动流,Dashboard 的 Cell 架构,开发流程和经验教训等精彩内容。)
翻译:包研,张志平,刘江;审校:刘江