http://developer.51cto.com/art/201305/395757.htm

  每月超过30%的增长当然不可能没有挑战,其中可靠性问题尤为艰巨。每天5亿次浏览量,峰值每秒4万次请求,每天3TB新的数据存储,并运行于超过1000台服务器上,所有这些帮助Tumblr实现巨大的经营规模。

 

老的Tumblr构架

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

新的构架

  • 由于招人和开发速度等原因,改为以JVM为中心。
  • 目标是将一切从PHP应用改为服务,使应用变成请求鉴别、呈现等诸多服务之上的薄层。
  • 选择了Scala 和 Finagle
    1. 在团队内部有很多人具备Ruby和PHP经验,所以Scala很有吸引力。
    2. Finagle是选择Scala的重要因素之一。这个来自Twitter的库可以解决大多数分布式问题,比如分布式跟踪、服务发现、服务注册等。
    3. 转到JVM上之后,Finagle提供了团队所需的所有基本功能(Thrift, ZooKeeper等),无需再开发许多网络代码,另外,团队成员认识该项目的一些开发者。
    4. Foursquare和Twitter都在用Finagle,Meetup也在用Scala。
    5. 应用接口与Thrift类似,性能极佳。
    6. 团队本来很喜欢Netty,但不想用Java,Scala是不错的选择。
    7. 选择Finagle是因为它很酷,还认识几个开发者。
    8. 之所以没有选择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上插入并发,也会遇到读复制延迟问题。
  • 此外,还开发了一个公用服务框架:
    1. 花了很多时间解决分布式系统管理这个运维问题。
    2. 为服务开发了一种Rails scaffolding,内部用模板来启动服务。
    3. 所有服务从运维的角度来看都是一样的,所有服务检查统计数据、监控、启动和停止的方式都一样。
    4. 工具方面,构建过程围绕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实例。
    1. Redis主要用于Dashboard通知的后端存储。
    2. 所谓通知就是指某个用户like了某篇文章这样的事件。通知会在用户的Dashboard中显示,告诉他其他用户对其内容做了哪些操作。
    3. 高写入率使MySQL无法应对。
    4. 通知转瞬即逝,所以即使遗漏也不会有严重问题,因此Redis是这一场景的合适选择。
    5. 这也给了开发团队了解Redis的机会。
    6. 使用中完全没有发现Redis有任何问题,社区也非常棒。
    7. 开发了一个基于Scala Futures的Redis接口,该功能现在已经并入了Cell架构。
    8. 短地址生成程序使用Redis作为一级Cache,HBase作为永久存储。
    9. Dashboard的二级索引是以Redis为基础开发的。
    10. Redis还用作Gearman的持久存储层,使用Finagle开发的memcache代理。
    11. 正在缓慢地从memcache转向Redis。希望最终只用一个cache服务。性能上Redis与memcache相当。
posted on 2014-05-11 20:18  FelixJia  阅读(438)  评论(0编辑  收藏  举报