您的位置:首页 > 运维架构 > 网站架构

Tumblr 的架构演进过程

2014-05-01 22:04 453 查看


老的架构

Tumblr最开始是托管在Rackspace上的,每个自定义域名的博客都有一个A记录。当2007年Rackspace无法满足其发展速度不得不迁移时,大量的用户都需要同时迁移。所以他们不得不将自定义域名保留在Rackspace,然后再使用HAProxy和Varnish路由到新的数据中心。类似这样的遗留问题很多。

开始的架构演进是典型的LAMP路线:
最初用PHP开发,几乎所有程序员都用PHP
最初是三台服务器:一台Web,一台数据库,一台PHP
为了扩展,开始使用memcache,然后引入前端cache,然后在cache前再加HAProxy,然后是MySQL sharding(非常奏效)
采用“在单台服务器上榨出一切”的方式。过去一年已经用C开发了两个后端服务:ID生成程序Staircar(用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异步网络应用框架,2月4日刚刚发布3.3.1最终版),但不想用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里打标签,发布到代码库等等。大多数程序员都不用再操心构建系统的细节了。

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实例。
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相当。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: