Foursquare的MongoDB宕机事件

Foursquare最近经历了长达11小时的宕机。宕机是由于他们的MongoDB出现了数据的不均衡增长,而这一点并没有被事先检测到。由于数据分散的原因,当Foursquare试图增加一个分区时没有成功,需要数据库离线才能对数据进行压缩。这也导致了系统宕机时间的延长。这篇文章提供了更多细节,记录当时发生了什么,为什么系统会宕机,Foursquare和10Gen对事故的响应。

Foursquare是一个成长极为迅速的基于位置服务的社交网络,8月份注册用户已经达到三百万。10月4日,由于快速增长的数据,Foursquare经历了11个小时的宕机。Foursquare的运营总监Nathan Folkman写了一篇博客,一方面向用户道歉,一方面提供了事故发生的一些技术细节。随后10gen的首席技术官Eliot Horowitz写了更为详细的文章,发布到MongoDB的用户邮件列表上。10gen开发了MongoDB,并为Foursquare提供技术支持。这篇分析文章引发了热议,包括Foursquare的工程师Harry Heymann,提供了更多细节。

基础系统架构

本次受到影响的关键系统是Foursquare的用户登入数据库。不像许多历史数据库只有小部分数据需要随时访问,10gen的首席执行官告诉我们,“由于种种原因整个数据库被频繁访问时,会导致工作集与整个数据库的大小差不多”。因此,数据库对内存大小的需求就等于数据库中所有数据量的大小。假如数据库的大小超过了机器内存,机器性能就会出现很大的摇摆,4块硬盘不能再负载更多的I/O请求。对于这个的问题,他说,“被频繁访问文档,其频率远远高于你们的预期”。

最初数据库运行在一个单实例EC2节点上,66G内存。大约两个月之前,Foursquare几乎耗尽了所有内存,于是他们把系统迁移到了具备两个Shard节点的集群环境中。每个Shard有66G内存,为了冗余,数据被复制到Slave节点。经过这次迁移之后,每个Shard大概有33G的数据。由于Shard上的数据是“通过用户ID平均分成200片进行存储的”,结果就是,给定用户的所有数据会被保存在一个独立Shard上。

宕机

由于用户持续增长,分区以一种不均衡的方式在增长,Horowitz指出:

MongoDB会对片进行分割,每到200M就切分为2个100M。最后的结果就是当整个系统的数据超过116GB时,一个分区数据是50G,另一个会达到极限66G,超出的请求会分散到磁盘上,性能大幅下降,从而导致系统宕机。

运营团队试图修复系统,为数据库增加了第三个Shard,希望把系统数据的%5转移到新的Shard上,这样就和内存相匹配了。他们仅仅迁移了5%的数据,Horowitz说,“我们试图迁移最少的数据,让网站尽可能快的恢复”。但是,这种方式并没有缓解整个Shard的性能问题。正如Horowitz所言:

迁移数据的稀疏是因为数据太小了,而且由于“在Shard中Key的顺序和插入顺序是不一样的,妨碍了在连续的块中迁移数据”。为了解决性能问题,他们不得不压缩整个Shard。目前MongoDB仅支持对Shard的离线压缩。数据的压缩,加上EBS(Elastic Block storage)的缓慢,导致整个过程花费了4小时。在为Shard释放了5%的空间之后,系统终于重新上线,至此,本次宕机事故持续了整整11个小时。在这次突发事件里,没有数据丢失。

跟进

系统恢复之后,Foursquare增加了多台额外的Shard,保证分布数据的均衡。为了解决碎片问题,他们对每个Slave节点的分区进行压缩,然后把Slave节点切换为Master节点,再对Master节点进行压缩。最后每个分区使用大约20GB的空间。

Horowitz表示:

Horowitz指出:

Foursquare小组也做出响应,承诺加强沟通,改进操作流程,如Folkman所言:

Heymann表示:

 

社区反应

针对这篇文章,社区提出了一系列问题:

  1. Nat 问:

    Horowitz 答:
  2. Alex Popescu 问:

    Horowitz 答:
  3. Suhail Doshi 问:
    Horowitz 答:
  4. Nat还问了反向压力问题:“看起来当数据的增长超过内存时,性能会明显降低”。

    对于该问题Roger Binns补充如下:


还有一些讨论,是关于固态硬盘驱动能否改善性能,但并没有确切的结论说明固态硬盘能够影响性能。还有人想知道为什么用户ID分区会以不均衡的方式增长。通过用户ID划分的分区大体上来说是均衡的──可能是有倾向性的分区(例如把旧用户放到一个Shard上)会导致不均衡的数据增长。

监控和未来的方向

为了更好的理解这个案例中的问题,我们采访了10gen的CEO Dwight Merriman。我们问了如何更好的监控大规模部署的MongoDB,他回答说需要依赖很多监控工具,Munin是很常用的工具,而且它有MongoDB的插件。我们问道:

根据以上描述,应该能够对MongoDB进程使用的常驻内存进行监控,进而在Shard内存很低时告警,是这样吗?

假如数据库比内存大,MongoDB会像其他数据库一样,倾向于把所有内存当作Cache使用。那么使用全部内存就不是什么问题。相反的情况,我们就需要知道什么时候工作集最接近内存大小。对于所有数据库来说这都很难。有一个不错的方式就是是监控其物理I/O的读写,并注意其增长情况。

在Foursquare的案例中,Merriman同意,所有数据可以驻留在内存中,通过监控驻留内存或判断整个数据库的大小就足以预先监测问题。这就意味着,在Shard被用完之前,我们可以简单的定位到问题所在。事实上,无论监控是否到位,能否定位问题,好像没有人希望出现不均衡增长的情况。

我们还问到了由于这个案例的经验,10gen是否会在开发重点上做一些改变,Merriman的回答是他们会尽快完成后台压缩的功能。另外,Horowitz表示MongoDB应该“变得更加优雅。我们会尽快完成这些增强的功能”。Merriman指出,MongoDB将允许对象重新集群,把非活跃的对象放入硬盘的Page中,而且他们相信内存映射文件会运行的很好。Horowitz表示:

最大的问题是并发。虚拟机已经运行的很好了,问题是读写锁的粒度太粗。线程可能会引起比预期更大的故障。我们会通过以下几种方式处理这个问题:创建策略更加智能、真正的内部集合并发等。

 

查看英文原文:Foursquare's MongoDB Outage

 

 

你可能感兴趣的:(Foursquare的MongoDB宕机事件)