您所知道的有关MongoDB的一切都是错误的

2020-11-26 13:14:57

我不到一年前加入MongoDB,此后我学到了很多东西。在我开始在公司进行采访之前,我从未真正使用过MongoDB,尽管我已经看到了一些有关它的讨论,并且对它的使用看起来如此简单也印象深刻。

但是和其他许多人一样,我也听到过一些可怕的故事。 “它不做任何关系!”人们会说。 “如果要存储文档很好,但是如果以后要进行聚合怎么办?您将被困在错误的数据库中!而且无论如何!事务!它没有事务!”

直到我开始寻找该信息的来源时,我才开始意识到两件事:首先,这些帖子中的大多数都是十年前的,所以他们指的是已经使用了三年的产品,而不是成熟的产品,第二,他们所说的几乎所有内容都不再是真实的,在某些情况下是不真实的。

因此,我决定就在线提供的错误信息进行一次演讲(现在写这篇博客文章),并一一反驳每个神话。

里面有一个YouTube视频,里面有几只狗(狗?我想他们是狗)。您可能已经看过了-其中之一是那种对新技术的盲目追随者,他们完全购买了MongoDB,却并不真正了解他们购买了什么。另一只狗更理性,并且由于第一只狗拒绝降落而感到沮丧。

我的一个朋友在MongoDB的第一天就给我发送了与此视频的链接,以防万一我没看过。 (我看过。)在底部查看日期!该视频已经发行了十多年。当时真的很有趣,但是最近呢?那里几乎所有的东西都已经过时了。

我们不难过。实际上,MongoDB上的许多人都在T恤或笔记本电脑上贴上了角色。他有点像MongoDB上的非正式吉祥物。只是不要看视频寻找事实。并停止发送指向视频的链接-我们都看过了!

MongoDB是一个分布式文档数据库。群集(我们称它们为副本集)大部分是自我管理的-一旦您告诉每台机器群集中还有其他服务器,然后如果其中一个节点出现故障或网络出现问题,它们就会处理。如果其中一台计算机关闭或崩溃,则其他计算机将接管。群集中的每台服务器都拥有数据库中所有数据的完整副本。

群集用于冗余,而不是可伸缩性。通常,所有客户端仅连接到一台服务器-选定的主服务器,该服务器负责执行查询和更新,并将数据更改传输到辅助计算机,以防服务器出现故障。

您可以通过直接连接到辅助服务器来执行一些有趣的操作,例如运行分析查询,因为计算机的读取负载较小。但是总的来说,强制与次要数据库的连接意味着您将要使用稍微陈旧的数据,因此除非您准备做出一些妥协,否则您不应该连接至主要数据库。

MongoDB与传统关系数据库的不同之处在于,MongoDB除了能够将平整的数据原子存储在数据库的表中之外,还允许您将分层结构化数据存储在文档中-(通常)类似于JSON目的。文档存储在一个集合中,它实际上只是一堆文件。每个文档可以与集合中的所有其他文档具有不同的结构或架构。您也可以(并且应该!)根据您将要运行的查询种类和数据来为集合中的文档建立索引。恢复。而且,如果您希望进行验证以确保集合中的所有文档都遵循集合结构,则可以将JSON模式作为验证器应用于集合。

{'_id':ObjectId('573a1390f29313caabcd4135'),'title':'铁匠场景','全图':'固定摄像机注视着一个大铁砧,铁砧在后面,而铁砧在两侧。 :['Charles Kayser','John Ott'],'countries':['USA'],'director':['William KL Dickson'],'genres':['Short'],'imdb':{'id':5,'rating':6.2,'votes':1189},'released':datetime.datetime(1893,5, 9,0,0),'runtime':1,'year':1893}

上面的文档是一个示例,显示了1893年的电影!该文档是使用PyMongo驱动程序检索的。

请注意,有些值是数组,例如'countries'和'cast'。一些值是对象(我们称它们为子文档)。这证明了MongoDB文档的层次结构性质-它们不像关系数据库中的表行那样平坦。

还请注意,它包含一个本地Python日期时间类型用于``发布''值,以及一个特殊的ObjectId类型用于第一个值。也许这些实际上不是JSON文档吗?我会再回头...

如果您在apt get mongodb上的Debian Stretch上安装MongoDB,它将安装版本3.2。不幸的是,此版本已有5年历史了。自那时以来,已经有五个主要的年度版本,其中包含许多新功能,以及安全性,性能和可伸缩性方面的改进。

MongoDBis v4.4的当前版本(2020年10月)。如果要安装它,则应该安装MongoDBCommunity Server,但是首先请确保您已阅读有关MongoDBAtlas(我们的托管数据库即服务产品)的信息!

您几乎肯定会听说MongoDB是JSON数据库,特别是如果您最近阅读过MongoDB.com主页!

但是,正如我之前暗示的那样,MongoDB不是JSON数据库。它支持其他数据类型,例如ObjectId,本地日期对象,更多数字类型,地理图元和有效的二进制类型等等!

这看似微不足道的区别,但这很重要。与使用基于文本的格式存储结构化数据相比,存储,传输和遍历更有效,并且比JSON支持更多的数据类型,它在MongoDB中也无处不在。

在阅读MongoDB的第三方描述时,您可能会遇到博客文章,将其描述为BASE数据库。 BASE是“基本可用性;软状态;最终一致性”的首字母缩写。

但这种情况并非如此!这些部分中的某些从来都不是-MongoDB从未“最终一致”-更新流式传输并顺序地应用到辅助节点,因此尽管它们可能落后,但它们从来不会不一致。软状态显然描述了需要不断更新数据,否则数据将过期的情况也并非如此。

最后,如果拆除了太多节点以致无法达到法定人数,则MongoDB将进入只读状态(降低可用性)。这是设计使然。它确保在出现所有错误时都保持一致性和分区容限。

对单个文档的多个部分的更新始终是原子的;但是从v4.0开始,MongoDB支持跨多个文档和集合的事务。从v4.2开始,分片群集中的所有分片甚至都支持此功能。

尽管支持交易,但应谨慎使用它们。它们具有性能成本,并且由于MongoDB支持丰富的层次结构文档,因此,如果您的架构设计正确,则您通常不必跨多个文档进行更新。

关于MongoDB的另一个过时的神话是,您不能在集合或文档之间建立关系。您可以使用称为聚合管道的查询进行联接。它们非常强大,使您可以使用直观的查询模型来查询和转换多个集合中的数据,该模型包括一系列应用于流经管道的数据的管道阶段。

下面的示例文档显示了在查询连接订单集合和库存集合的查询之后,如何将返回的订单文档包含嵌入数组的相关库存文档。

我的观点是,与为关系联接中发现的每个关系复制行相比,能够将相关文档嵌入要返回的主文档中更为直观。

您可能会听到人们谈论分片是MongoDB的一项很酷的功能,而且-这绝对是MongoDB的一项很酷的核心功能。

分片是指对数据进行划分并将每个片段放入不同的副本集或群集中。这是一种处理庞大数据集的技术。 MongoDB支持自动确保将数据和请求发送到正确的副本集,并合并来自多个分片的结果。

我在本文前面提到,为了允许仲裁,areplica集合中的最小节点数为3。一旦需要分片,就至少拥有两个副本集,因此最少有六台服务器。最重要的是,您需要运行一个名为mongos的服务器的多个实例.Mongos是分片群集的代理,用于处理请求和响应的路由。为了获得高可用性,您至少需要两个mongos实例。

因此,这意味着最小的分片群集为八台服务器,并且至少增加三台服务器,并添加了每个分片。

群集还使您的数据更难管理,并且对您可以执行的查询类型增加了一些限制。如果需要,分片很有用,但是简单地升级硬件通常更便宜,更容易!

扩展数据主要与RAM有关,因此,如果可以,请购买更多RAM。如果CPU是您的瓶颈,请升级CPU或购买更大的磁盘。

一旦扩展到一台计算机可以容纳的RAM数量之外,MongoDB的分片功能仍然为您提供。您还可以使用分片来完成一些整洁的事情,例如地理固定,您可以在其中将用户数据存储在地理上更靠近用户位置的位置,以减少延迟。

如果您尝试通过分片进行扩展,则至少应首先考虑硬件升级是否会是更有效的选择。

在考虑之前,您应该先看一下MongoDB的hostedDatabase-as-a-service产品MongoDBAtlas。 (是的,我知道我已经提到过!)除了为您托管数据库之外,MongoDB Atlas还将根据需要上下扩展数据库,以保持可用状态,同时保持较低的成本。它可以处理备份和冗余,还包括其他功能,例如图表,文本搜索,无服务器功能等。

关于MongoDB的一个相当持久的神话是它从根本上是不安全的。我个人的感觉是,这是有关MongoDB的更不公平的说法之一,但是不能否认,Internet上存在许多不安全的MongoDB实例,而且涉及MongoDB的数据涉及数起重大事件。

历史上这是由于MongoDB的分发方式所致。某些Linux发行版本用于在禁用身份验证并启用网络的情况下交付MongoDB。

因此,如果您没有防火墙,或者在防火墙上打开MongoDB端口,以便Web服务器可以访问它,则您的数据将被盗。如今,机器人很可能会找到您的数据,在数据库中对其进行加密,然后添加一个文档,告诉您将比特币发送到何处,以获取再次解密它的密钥。

我会争辩说,如果您在互联网上放置不受保护的数据库服务器,那是您的错-但是,肯定是这种情况已经发生过很多次了,并且有很多方法可以使这种混乱变得更加困难。

我们已经修复了默认设置。除非启用了身份验证,否则MongoDB将不会连接到网络,或者您向服务器提供了一个特定的标志来覆盖此行为。因此,您仍然可能没有安全感,但是现在您至少必须先阅读本手册!

除此之外,MongoDB使用行业标准进行安全保护,例如TLS加密传输中的数据,使用SCRAM-SHA-256进行安全的用户身份验证。

MongoDB还具有客户端字段级加密(FLE)功能,该功能允许您将数据存储在MongoDB中,以便在传输过程中和静态时都对其进行加密。这意味着如果第三方要获取对您的访问权限,数据库服务器,它们将无法读取加密的数据而又无法获得对客户端的访问权限。

这个神话是经典的Hacker News trope。有人发布了一个示例,说明了他们如何成功地使用MongoDB构建内容,并且有直接评论说:“我知道这个人曾经在MongoDB中丢失了所有数据。

如果您跟进这些用户以进行联系并提交描述事件的票证,他们将永远不会出现!

更严重的是,MongoDB为Jepsen进行了几次测试运行,以确保即使在严峻的网络条件下数据的一致性。这些测试已添加到我们的自动化测试套件中。一些测试发现了错误-它们是故意的-我们已修复它们。对于Jepsen,对于MongoDB的默认值仍存在一些意见分歧,但是,如果您阅读该手册,则可以依靠MongoDB来一致,稳健地存储和维护数据。

MongoDB已被广泛关注其数据保存的许多行业使用。这些银行的范围从摩根士丹利,巴克莱和汇丰银行之类的银行到福布斯等大型出版品牌。我们从来没有关于大规模数据丢失的报告。如果您确实有第一手资料来讲述数据丢失的情况,请提交票证。无论您是付费企业客户还是开源用户,我们都会认真对待。

像任何数据库一样,MongoDB是一件大而复杂的事情。尽管上手非常容易,但是如果您不去某个地方阅读手册,那将会很麻烦。

您会错过真正想要或需要的功能,或者想要以一种不简单的方式优化数据库或进行扩展。

您不会在一夜之间成为专家。好消息是,有很多学习MongoDB的资源,这很有趣!

在MongoDB开发人员博客上,我们详细介绍了一些用于模式设计和开发的MongoDB模式。我的杰出同事LaurenSchaefer已经撰写了一系列描述MongoDBAnti-Patternsto的文章,可帮助您认识到您可能没有以最佳方式做事。

因此,MongoDB既庞大又复杂,还有很多东西要学习,但是我希望本文已经以某种方式解释了什么是MongoDB,什么不是MongoDB,以及您将如何学习有效地使用它。