Foursquare 长达 11 小时的宕机

今天是个值得庆贺的日子

前几天 Foursquare 经历了长达 11 个小时的宕机,没错,11 个小时。网站官方的解释是 Shard 负载不均匀造成后续的连锁反应。很多人都知道 Foursquare 在线的 DB 是 MongoDB,今天又看到 10gen (MongoDB的开发与支持团队)的 Eliot Horowitz 在得到 Foursquare 许可后,通过邮件组详细介绍了宕机的过程:Foursquare outage post mortem,不用说,也有为 MongoDB 辟谣的意味在里面。

读罢 10gen 团队的介绍(或者说解释)之后,发现这是一个很好的研究样本。值得分享。

为了提高响应速度,Foursquare 使用 MongoDB 存储 Check-in 的数据已经有一段时间了。这部分数据的数据库起初跑在一个 66GB 内存的 Amazon EC2 单实例上(全部在内存里),两个月前,出于对容量增长的考虑,迁移到两台 Shard 集群上。每个 Shard 机器都是 66GB 内存,为了冗余,每个 Shard 都有复制到 Slave 实例。迁移的目标是所有的 Check-in 数据都保存在内存中。数据根据 ID 分成 200 个 Shard 分片,两台机器各占一半,也就说联机数据在每台机器上各使用 33GB 的内存。两个月相安无事。

问题来了,因为 Shard 算法导致的数据分散不均衡,其中一台(Shard0)数据增长到 67GB(另外一台 50GB),超过了 66GB 的限制,读写部分分散到磁盘上,性能急剧下降。从而,网站宕机。

首先尝试增加第三台 Shard 机器,上线后开始迁移,读取从三台进行,Shard0 的数据迁移到 5% 的时候,但是写操作还是让 Shard0 宕机了。这个时候发现Shard0 存在数据碎片(data fragmentation),即使数据迁移走,还是会占用原来的内存。每个Check-in 文档大约占用 300 字节,而 MongoDB 是 4KB 的页(Page),也就说十几个文档会填满一个页,而迁移 5% 反而造成了页更加稀疏,并不是将页全部删除。

这个时候已经到了第二天,随着网站全面宕机,技术团队开始用 MongoDB 的 repairDatabase() 功能来对数据库进行压缩,因为数据库太大和 EBS 慢,也因为 repairDatabase() 不能充分利用多核CPU 的能力,这个过程耗费了 4 个小时。之后这 5% 的内存空间终于释放出来,系统重新上线。

随着 Shard0 修复,第三台成功上线,进而添加了更多的 Shard 服务器,现在数据已经更加的均衡,通过在Slave上运行 repairDatabase(),然后将其切换到 Master ,每台 Shard 内存占用缩减到 20GB左右。整个故障时间已经延续了 11 小时之多。

产生问题的主要原因就是系统过载,前面介绍每台 Shard 承载原来 50% 的压力,到了问题发生的时候,单台 Shard 的负载已经超过 Shard 之前的系统负载,这时候已经积重难返了,在容量的临界点增加新系统资源,必然导致更多的停机时间。暴露了 Foursquare 团队在容量规划方面的不足之处,或许也因为业务增长太快了吧。另外,内存碎片化的问题在没有宕机之前,技术团队应该没考虑过这个问题,如果文档的大小超过 4K,碎片化问题就不严重了,这是特定应用场景造成的特定问题。10Gen 现在已经着手研究如何进在线压缩(online compaction)。再次,Shard 键值的顺序和插入顺序是不同的,这造成了迁移数据的时候 Chunk 的迁移不是连续的。

这个过程给我们的启示是:最近 NoSQL 已经成为一个热词,类似 MongoDB 这样的新事物当然值得尝试,但是不能冒进,因为驾驭起来并非易事。仅仅能够使用是不够的,系统没出问题一切都好,一旦出了异常,有足够的技术力量(设想一下 Foursquare 得不到 10gen 团队的支持会如何?) 支持么?在极端情况下如何控制? 如果回答不了这个问题,那么还应该暂缓。最好的办法就是…”等待”。

给我的另一个感慨是 Amazon 在云计算领域已经真的成为一个赢家,而且越来越得到 Web 2.0 Startup的信赖。前面说的 66GB 内存,应该指的是EC2 的 “High-Memory Double Extra Large Instance”,可提供的最大内存是 68.4 GB 。CPU 和内存能力都是可以接受的,存储方面的性能似乎还有点不足,也就是其中的 EBS ,指的是 Amazon Elastic Block storage。

EOF

从 C10K 到 C500K

还在谈 C10K 的问题?这个已经过时了,现在大家已经开始说 C500K

国外的 Urban Airship 公司的工程师在其官方网志上发文章介绍他们在产品环境中做到 50 万并发客户端,Java + Pure NIO 的实现,最近又有文章介绍针对 Linux Kernel 调优的经验:Linux Kernel Tuning for C500k 。并且指出了”单个 IP 最大并发数量上限为64K” 只是一个误解。

硬件环境?操作系统为 Ubuntu(Lucid),租用 Amazon 的 EC2 ,使用 EC2 Large instances,64 位操作系统,每个 7.5 GB 内存。

当然,Urban Airship 是做手机消息 Push 服务的(Android Push 架构),所以,如果你也要做到这样的并发,还要看你的应用场景是否合适。去年了解到曾在新浪、腾讯任职的杨建已经做到超过 20 万的 HTTP 并发(现在可能已经突破这个限制了),非常的惊人。我非常想知道现在各个公司在这方面的实践数据。

EOF

另外参考:A Million-user Comet Application with Mochiweb

更新:杨建同学发来消息,去年已经单击突破 46.5万 Connections, 两块网卡, 1.5G 输出。10万请求处理每秒,每个响应 2k 左右。据说当时遇到一个坎一直没能过 50 万,不过这个坎三个月前已经过了,现在过 60 应该没悬念,四核双 CPU 机器。据杨建说,”按现在 4 Core * 4CPU 的机器,我觉得可以冲刺 80~100万,前提需要4块网卡(千兆)”。可见,把事情做到极致是没有极限的。

此文作者:, 位于 Arch 分类 标签: on .
转载须以超链接形式标明文章原始出处和作者信息及版权声明.

Facebook 针对 MySQL 开源 Online Schema Change 代码

有过 MySQL 使用经验的人应该知道,MySQL 要想在线修改个 Schema 结构是个麻烦事,规模不大的表增加个索引造成的锁也可能导致整个 Web 应用宕机。这一点没办法和 Oracle RDBMS 、DB2 等商业数据库相比,甚至 PostgreSQL 也具备联机 DML DDL 的能力。我在过去写过一系列并不成熟的《MySQL 大企业级应用可行性分析》 文章中,也很是担忧这个问题。有些公司想迁移到 MySQL ,也因此而只能采取保守的做法。

不过现在这个缺陷临近被彻底修复。Facebook 的数据库技术团队将 Online Schema Change (OSC) 的代码开源,并且撰文进行了详尽的阐述。这是个很大的技术革新,Facebook 数千台 MySQL 服务器在过去增加个索引需要几个月的滚动升级,现在只需要几天即可。

MySQL 5.1 的 InnoDB 引擎具备 Fast Index Creation 的功能,在创建索引的时候无需复制整个表的内容,但是对于一定规模的大表增加索引,仍然需要花费大量时间,对于在线应用来说,仍然不可忍受。而 Facebook 的 OSC 则进一步进行了改进。对于 MySQL DBA 来说,这是个福音。感谢 Facebook 的员工 Vamsi Ponnekanti 的工作。如果要我说,年度 MySQL DBA 应该授予给他。当然,Online Schema Change 的部分代码从 Shlomi Noach 的 Openark Kit 中派生,建议 Shlomi Noach 一同获奖…

对于 MySQL 来说,我认为这是个里程碑式的时刻,无论 Oracle 将给与 MySQL 多大的投入,其它公司已经主动拿过接力棒。Facebook 技术团队再次立功了!

EOF

Update: Facebook 工程师在帖子里说了”Note that the above operations can be done within the storage engine itself, or using an external (PHP) script.” 要知道,这并非只是一个 PHP 脚本的实现。我建议技术人员看帖子应该更仔细一些。也不要说这东西你早都想到了之类的技术阿Q的话,我倒现在为止没听到国内一个公司的技术人员做出来这东西。从想法到实现,其实还有十万八千零一公里呢。

MySQL Sunday 见闻

Oracle Open World 第一天一般是注册日加上 Keynote,但这次下午安排了 MySQL Sunday 的活动,这倒是 Open World 上第一次出现 MySQL 的活动,去年可能正在忙于和 Sun 整合,来不及安排吧。之前,搜索了一下议程,有两场 Facebook 的工程师的 Session,早早赶到会场,听完虽然感觉料不够多,但也很过瘾。

Facebook 进行分享的两位工程师分享的议题一个为 Advanced MySQL Replication Techniques ,MySQL Team 的 Harrison Fisk 是演讲人,另一个话题为 Success with MySQL ,分享人是 Mark Callaghan,他也是 MySQL Engineering Team 的 Lead,Facebook 有个 MySQL Performance Team,是介于运维护与工程师之间的团队。演讲的过程中除了 Facebook 之外只能听到 Google,其它公司或许不值一提,也或许是 Facebook 和 Google 渊源颇深的缘故吧。

Facebook 的数据库团队之所以能够维护几千台 MySQL DB,和他们对 MySQL 代码层的驾驭能力有很大关系,Facebook 自己就发布了不少 MySQL 的 Patch(在 Lunchpad 上可以找到),另外,Google 发布的 Patch 对他们来说也有很大帮助。此外,Facebook 也是当前世界上最大的 Memcached 用户,MySQL 的压力反而小了很多。基本上 DB 是用来做关系数据的存储以及跨 IDC 的数据同步。Faceook OLTP 环境的一些基本数据:查询响应时间 4ms ,写操作的响应时间为 5ms, 峰值每秒钟读取 3.5 亿行数据,修改行数为 350 万行,网络峰值吞吐量为 38GB,每秒钟应对的查询有 1300 万次。相当的惊人。大一点的表基本都进行了 Sharding,会后问了一下,Facebook 目前也没有使用 SSD,但是在做初步测试。

MySQL_Sunday.jpg
(这是 Facebook 之前的演讲现场,会场人不多,毕竟是第一天报到日)

会场同时也有其它关于 MySQL 的演讲,有关于 MySQL 5.5 新特性的介绍以及一些业界公司的 DBA 分享经验,可惜的是,人不算特别多,可能是听众目标不是集中的缘故吧。很多人的兴趣都还在傍晚时候 Oracle CEO 的主题演讲,当然,那些猛料这会儿大家应该都知道了。

EOF