Scrapinghub在早期就因其便利性采用了MongoDB来存储我们抽取到的数据。我们所抽取到的数据的表示形式为可序列化成JSON的记录(有可能有嵌套)。存储数据所用的schema无法事先确定,可能会随着任务的不同而不同。对于存储好的数据,我们需要支持对其进行浏览、查询和下载。采用MongoDB可以非常容易地实现这个目标(在几年前的当时同其它可选方案相比要容易),随后的一段时间内它的表现也很好。
MongoDB刚开头就是用作一个简单的数据存储,只是在几个项目中存储我们所抽取到的数据,后来它逐步发展为我们的Scrapy云平台的后端数据库。时至今日,我们目前系统架构的局限日渐暴露,因此我们不打算再接着使用MongoDB了,下定决心要换用一种不同的技术(细节会在随后的博文中给出)。我们的许多客户听说我们要抛弃MongoDB了,感到十分惊讶,我希望这篇博文能够帮我们解释清楚为什么MongoDB已再不适合我们了。
我们的网站中有大量可迅速完成的查询,其中大部分是来自网页抓取中产生的写入请求。这些查询很少会造成问题,因为它们执行起来速度很快,而且其总体数量也是完全可预测到的。然而,我们还有一些相比数量较少的、运行时间也会比较长一些的查询(比如,数据导出、过滤、批量删除、排序等等)。当有少数的这两种查询在同时运行时,就会造成锁竞争。
每个MongoDB数据库(2.2之前的服务器)都具有一个Readers-Writer锁。由于产生了锁竞争,所有的可迅速完成的查询不得不多等一些时间才能得以执行,而原本执行时间较长的查询执行起来需要的时间更长了! 可迅速完成的查询由于等待的时间过长从而引发超时并会在随后再进行重试。对我们网站所发的请求(比如用户在浏览数据)处理起来所需的时间如此之长,以至于我们的Web服务器中所有的工作线程都阻塞于对MongoDB的查询。最终,我们的网站和所有的网页抓取程序就都停止运行了!
为了解决这个问题,我们:
MongoDB并不自动收回被删除对象所占的磁盘空间,并且在不造成较长的停机时间的情况下想手动回收这些空间也不可行(因为有锁)。它会在插入新的对象时重新利用这些空间,当这样一来数据的碎片化非常严重。由于有锁的存在,不停机我们也不可能对碎片进行整理。
我们抽取到的数据压缩率一般都比较高,但很不幸的是,MongoDB不具有内置的压缩机制。我们在插入数据前进行压缩也毫无意义,因为每个单个的记录往往都比较小,而且我们还需要对数据进行查询呢。
总是把对象字段的名字也存储起来也会造成空间浪费,特别在某些collection中我们对它们从不进行改变的情况下更是如此。
为了便于处理我们运行的MongoDB下建了大量的数据库。每个数据库分配了最小的空间,如果数据库中的数据量比较小,就会造成空间浪费。如果磁盘缓冲区中还没有数据(例如数据库刚重启),那么MongoDB启动起来就要花比较长的时间,这是因为它要对每个数据库进行检查。
有些数据(例如网页抓取日志)需要按照它们当初写入的顺序返回给客户端。按顺序检索出数据还需要排序在记录的数据量比较大的情况下就很不现实了。
在MongoDB里只有适用capped collection才能保持数据的顺序,但它又不适用于页面抓取数据的输出。
每个抓取作业中要写入的条目数没有限制,要写入百万个条目的作业可不罕见。要从一个抓取作业的中间部分开始读取数据,MongoDB还需要从开头处的索引遍历到指定的偏移处开始读取。对于具有大量数据的作业,后部的数据读起来非常慢。
用户可以通过我们提供的API从分页的查询结果中下载作业数据。对于大型作业(比方说,作业中有百万级的条目),速度会非常慢,有些用户会通过同时发出多个查询来解决该问题,但这无疑会造成服务器负载高起并产生锁竞争。
MongoDB有一些奇怪的限制条件,比如在对象的字段名称中只允许这些字符。这样可不好,因为在这方面我们控制不了我们需要保存的字段名。
每个节点我们都有 TB 数量级的数据。 那些频繁访问的数据是很小的,当然可以将它保留在内存中。而那些不频繁访问的数据通常是通过顺序抓取得到的数据。 (原文:The infrequently accessed data is often sequentially scanned crawl data.)
MongoDB 并未给我们提供足够的控制如何去存储数据,那么那些频繁访问的数据(以及那些扫描得到的数据)就可能散布在较大的区域之中 。 若 只扫描数据 一次, 就无法 回收这些 数据 所占内存的内存空间 。 一旦 频繁访问的数据 不保存在 内存 , MongoDB 的 IO绑定 和 锁竞争 就成了一个问题 。在接触MongoDB之后,我们将它应运到了许多地方,包括运行在后台为我们的Diango UI 服务。那些数据本该是整洁的,结构化的, 但是MongoDB 却使得一切变得糟糕。MongoDB本身的局限性如下:
MongoDB的确有它所适用的场合。许多客户告诉我们说,它们采用MongoDB存储网页抓取数据的效果很不错。在Scrapinghub也有过这么一段时间,但是,对于我们的需求来讲,它不再合适了,在这篇博文里提出的这些问题我们难以克服。
我将在近期的博文中对我们所采用的新式存储系统进行描述,如果你感兴趣的话,请关注 @scrapinghub!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务