我读到了一篇关于红帽公司的 Satellite 不再支持 MongoDB 的帖子,我也知道很多人认为此举源自许可条款方面的修改。这不禁让我想起过去几年来,一直不断有关于 MongoDB 如何可怕、以及用户不应该将其作为选项的声音与文章。然而,就在这重重阻力之下,MongoDB 仍然发展成一款更为成熟的产品。那么,到底发生了什么?一切反对的声音,真的单纯来自 MongoDB 早期实施 / 营销过程中犯下的错误吗?或者说,人们一直没能真正客观准确地评判 MongoDB 是否适合自己?
读到这里,很多朋友可能认为我是打算帮 MongoDB 辩护一番。关于这个问题,请大家参考本文末尾的免责声明,我会在那里明确表达自己的立场。
趋势聚焦
首先需要说明的是,多年以来我一直在使用各类软件;但即使如此,我也仅仅经历了冲击整个行业的诸多趋势当中的一小部分。我目睹了 4GL、AOP、敏捷、SOA、Web 2.0、AJAX 以及区块链等等事物的崛起……继续列举下去,这份清单几乎可以无穷无尽。每一年都会出现改变整个软件工程领域的新趋势。其中一些很快陷入困境,而另一些则从根本上颠覆了软件的开发方式。
当任何一种创新成果带着巨大的吸引力出现在我们面前,人们很快开始积极涌入,而这又会引导更多本打算旁观一下的受众参与其中,最终在整个行业掀起一般热潮。Gartner 公司专门就此发布相关报告,其定义的炒作周期(虽然存在争议)确实在很大程度上正确评估了有价值技术从诞生到发展再到趋于成熟 / 消亡的整个过程。
但每隔一段时间,又会出现一种不同于其它的创新(有时候也表现为旧有技术再度复苏)。这种创新由其中的某一特定实现所驱动。以 NoSQL 浪潮为例,其就受到了 MongoDB 出现以及快速崛起的重大推动。MongoDB 并不是这股潮流的直接推手;它只是一种恰逢其时的解决方案,正好遇上互联网巨头们遭遇的数据挑战只有非关系数据库才能很好 地解决。正因为如此,谷歌公司的 Bigtable 与 Facebook 的 Cassandra 等项目相继出现。然而,MongoDB 仍然是大多数开发人员最易于获取、同时也最为熟悉的 NoSQL 数据库选项。
旁白:说到这里,大家可能会想,我这不是把列数据库、键 / 值存储或者多种其它数据存储类型都给混杂到 NoSQL 这个阵营里头了吗?哈哈,这里我得说一句,您说得没错!但那个时候,这种混淆就是现实,而且相当严重。每个人都高举着 NoSQL 的旗帜,每个人都坚称他们离不开 NoSQL——但实际上,他们并没有真正理解其中涵盖的不同技术元素。对于很多人来说,MongoDB 实际上就是 NoSQL。
开发人员对此做出了积极的回应。无模式数据库能够近乎无限地扩展,因此可以应对任何挑战的基本思路确实非常诱人。因此在 2014 年左右,我们发现几乎到处都有人在使用 MongoDB——正如短短一年之前,还到处有人在使用 MySQL、PostgreSQL 或者 SQL Server 这类关系数据库一样。在被问到为什么要使用 MongoDB 时,他们的回应各不相同:从常见的“实现网络规模扩展”到“我的数据结构非常松散,特别适合无模式数据库”可谓不一而足。
最重要的是需要明确一点,MongoDB 以及文档数据库这一类解决方案,能够帮助人们搞定很多传统关系数据库无法应对的难题:
严格的模式:在传统数据库当中,如果我们掌握的是动态数据,则必须创建一堆随机的“杂项”数据列以将数据作为数据块进行推送;或者使用 EAV 设置等等……而这一切,都有着严重的缺陷。难于扩展:在传统数据库当中,如果我们的数据规模太过庞大则将无法被直接存放在单一服务器当中;相比之下,MongoDB 的内置功能允许大家跨越多台计算机实现数据扩展。架构修改难题:可迁移!在使用关系数据库时,变更数据库结构无疑是一项巨大的挑战(特别是在您的数据量不断增大这一背景之下)。MongoDB 承诺显著简化这一过程,使得结构调整变得更为轻松顺手,用户能够持续更新架构并快速完成迁移。写入性能:MongoDB 的性能相当不错,特别是在配合正确的配置方式之后。MongoDB 开箱即用的写入配置虽然成为不少人抨击它的理由,但也确实带来了一些令人印象深刻的性能数字。
买者自负
MongoDB 能够带来的潜在优势无疑是巨大的,面对特定问题类型的用户确实可以从中获益良多。如果不配合其它背景信息或者不具备使用经验,看了上文的朋友一定认为 MongoDB 真正改变了数据库系统领域的游戏规则,甚至堪称整个行业的大救星。情况当然没那么绝对——除了上述优势之外,MongoDB 也存在不少问题,下面我会一一列出。
公平地讲,10gen/MongoDB 公司并不是没有考虑到这些问题,他们只是做出了自己的权衡。
事务丢失:事务可以说是众多关系数据库(注意,不是全部,但确实是大多数)的核心特征。事务机制意味着用户能够以原子方式执行多项操作,并始终确保数据内容保持一致。当然,使用 NoSQL 数据库,您也可以在单一文档当中包含事务,或者使用两段提交等策略获得类似事务的语义。但关键在于,这一切必须得由用户亲自动手完成……而且要保证一切正确无误,可能是一项颇具挑战且需要投入大量精力的工作。事实上,除非数据库中的数据已经进入无效状态,否则我们通常会意识不到究竟出现了多少数据丢失问题——究其原因,是因为我们无法保证操作的原子性。 注意:很多朋友可能要提醒我,MongoDB 4.0 已经于去年引入了事务机制,但其中仍然存在不少局限性。正如不少报道已经指出,用户需要首先评估其能否满足自己的需求。关系完整性(外键)丢失:如果您的卖QQ平台数据之间存在关系,那么这种关系就是一种客观现实。几乎所有数据中都包含某种关系,如果数据库没有强制体现这些关系,就得由应用程序负责构建。具体来讲,由数据库强制执行这些关系将帮助应用程序减轻大量负担,从而降低软件工程师们的日常工作量。缺乏执行数据结构的能力:强模式有时候代表着一种短板,但其同时也可能成为确保数据拥有良好结构的有力机制。只要加以合理运用,其就能够提供一种强大的机制,用以确保您的数据在结构上与您的期望完全契合。相比之下,MongoDB 这类文档数据库能够在模式层面带来令人难以置信的灵活性,但这种灵活性同时会将责任转嫁到维护者身上,强制要求其保持数据清洁。如果没有给予应有的关注,那么我们最终不得不在应用程序当中添加大量代码,从而消化那些在结构上与预期不符的数据。相信很多朋友都听过这样一句话:你的应用总有一天需要重写,但数据却将永远存在。 注意:MongoDB 支持模式验证,这项功能非常有用,但却仍无法带来可与关系数据库相媲美的保障。首先,添加或修改架构验证不会影响集合中的任何现有数据,因此我们需要自行确保数据更新以匹配新的架构。换言之,到底是否满足需求还是得由用户自己决定。缺少自定义查询语言 / 工具生态系统:SQL 在刚刚出现时绝对掀起了一场革命,而且时至今日仍然代表着一种客观标准。SQL 是一种非常强大的语言,但同时也给用户带来了使用挑战。我们必须使用由 JSON 片段组成的自定义查询语言查询数据库;即使对于经验丰富的 SQL 专业人士而言,这也绝对不是一项轻松的工作。另外,SQL 数据库拥有一整套互操作工具,从 IDE 到报告工具皆在其中。而一旦将数据迁移至不支持 SQL 数据库,即意味着其中大多数工具将无法继续使用。更可怕的是,即使想找到新的办法将数据放入能够继续使用这些工具的其它 SQL 数据库,其难度也远远超过大多数人的想象。
很明显,不少决定使用 MongoDB 项目的开发人员并没有深入理解他们做出的权衡究竟意味着什么。事实上,很多开发者常常将 MongoDB 视为应用程序的主数据存储区,而这样的决定通常意味着极为昂贵的维护成本。
还有哪些不同的解决思路?
当然,并不是每位开发者都会盲目跳进这个坑,然后摔个晕头转向。但这样的情况也着实不少,相信未来几年会有不少项目在意识到问题后将 MongoDB 剔除出去。虽然有马后炮的嫌疑,但如果这些组织能够在做出技术选择之前先拿点时间按部就班进行一番思考,那么完全有能力避免这样的折腾。
那么,我们该如何确定哪些技术方案对自己的用例具备实际意义?目前已经出现不少尝试性项目,希望就技术评估工作构建一套系统性框架。但我认为,事情本不需要弄得这么复杂。
只需要提出两个主要问题,就足以合理评估众多技术方案;但其中的挑战在于找到能够负责任地回答这些问题的人,他们愿意花时间回答这些问题,同时确保答案当中不存在任何偏见。
如果没有遇到某些特定问题,就不需要引入新的工具。就这样。
问题一:我打算解决什么问题?
如果我们没有遇到某些特定问题,就不需要引入新的工具。说完。不要拿着解决方案反回来寻找问题,这是一种为了使用工具而使用工具的行为。换言之,如果不存在能够证明新技术优于现有技术的具体需求,那么就不要费力搞些没必要的决策。很多朋友可能是因为看到其他人在用某些新方案,才决定就其必要性进行一番讨论。在这种情况下,我们不妨从最简单的层面出发:他们到底面对着怎样的问题,您又是否面对同样的问题?观察其他人的行为倾向非常简单,但合理评判其行为在我们自己场景中的适用性却相当困难。
问题二:我放弃了什么?
这个问题明显更难回答,因为我们必须深入剖析并确保对旧有 / 新的技术都拥有很好的理解。有时候,在利用新技术构建某些实际方案之前,我们不太可能真正理解其内涵。或者,我们必须找到那些曾在新技术身上投入过大量时间的实践者并听取他们的意见。
如果这两种方式都不可行,那么您真的需要考虑如何通过最小投资确定该工具是否具有价值。另外,如果进行了前期投资,又是否会增加撤销计划的难度?
人类总会把事情弄糟
我们必须记住,在尝试以客观中立的方式回答这些问题时,总会有人性因素跑出来作祟。为了有效评估技术,我们必须克服一系列认知偏见,下面仅举几例:
从众心理 – 每个人都听过这种说法,但却仍然很难摆脱出来。总之,请确保在选择技术时,完全是因为它能够解决您的实际需求,而非某些看似很牛的家伙也在做同样的事。厚今薄古 – 不少软件开发人员总是倾向于低估长久以来使用的原有技术,同时过高估计新技术带来的好处。这不是软件工程师所特有的问题,每个人骨子里都有点这样的毛病。存在偏见 – 我们都倾向于关注已经存在的情况,并忽略尚不明确的情况。而这一点与“厚今薄古”心态交织起来,有可能造成严重的破坏。因为这意味着我们不仅在本质上就更认可新技术,同时也在刻意忽略新技术中存在的弊端。
客观地看待事物是一种挑战,而了解并努力克服可能影响判断的偏见,将帮助大家做出更为合理的决策。
总结陈词
当某一创新成果出现(或者复苏)时,我们需要非常谨慎地回答以下两个问题:
这款工具是否能为我们解决实际问题?我们是否真正理解该工具在开发中所做出的权衡?
如果您无法自信地回答这两个问题,请退后一步重新进行评估。
那么,让我们回到主题:MongoDB 到底是不是理想的数据库选项?是的,它当然是;但与大多数软件工程问题一样,这得分具体情况。对于那些为这两个问题找到了确切答案的团队而言,其中很多人发现了实际价值,并正在不断挖掘 MongoDB 的巨大潜力。而对于那些还没有回答这些问题的朋友,希望大家能够从中掌握一些应对炒作周期的宝贵教训——也祝愿各位不要在学习过程中付出过高的代价。
免责声明
这里我想澄清一点,我既不喜爱 MongoDB,也不讨厌它。简单来说,我一直没遇上过真正适合利用 MongoDB 处理的现实问题。我知道,10gen/MongoDB 公司确实犯过一些错误,包括在项目推出早期采用不安全的默认设置,并在一切应该或者不应该的场合下(特别是各种黑客马拉松活动)将 MongoDB 描述为一切数据需求的终极解决方案。没错,这些都是不太好的决定,但我也认为这些状况都为本文主旨提供有力的支持——所有问题,都可以通过技术评估快速发现。保持理智,拒绝盲目,同志们加油!