25

有一个微博类型的应用程序。两个主要的基本数据库存储是:MySQL 或 MongoDB。

我计划对大量数据进行非规范化,即对帖子进行的投票存储在投票表中,并且在主帖子表中增加计数。该帖子还涉及其他操作(例如,点赞、投反对票)。

如果我使用 MySQL,一些数据比固定模式更适合 JSON,以便更快地查找。

例如

POST_ID   |  activity_data

213423424 | { 'likes': {'count':213,'recent_likers' :
             ['john','jack',..fixed list of recent N users]} , 'smiles' : 
             {'count':345,'recent_smilers' :
             ['mary','jack',..fixed list of recent N users]}  }

该应用程序还有其他组件,其中建议使用 JSON。因此,要更新 JSON 字段,顺序为:

  1. 在 python 脚本中读取 JSON。

  2. 更新 JSON

  3. 将 JSON 存储回 MySQL。

这将是 MongoDB 中的单个操作,具有,$push等原子操作。MongoDB 的文档结构也很适合我的数据。$inc$pull

我在选择数据存储时的考虑。

关于 MySQL:

  1. 稳定而熟悉。
  2. 备份和恢复很容易。
  3. 使用某些字段作为无模式 JSON 可以避免未来的一些模式更改。
  4. 可能要提前使用memcached层。
  5. JSON blob 在某些表(如主帖子)中将是静态的,但会在其他一些表(如帖子投票和点赞)中进行大量更新。

关于 MongoDB:

  1. 更适合将架构较少的数据存储为文档。
  2. 缓存可能会被避免,直到稍后阶段。
  3. 有时应用程序可能会变得写密集型,MongoDB 可以在不安全写入不成问题的那些点上表现得更好。
  4. 不确定稳定性和可靠性。
  5. 不确定备份和恢复有多容易。

问题:

  1. 如果一半的数据是无模式的,我们是否应该选择 MongoDB,如果使用 MySQL,我们应该将其存储为 JSON 吗?
  2. 像主帖这样的一些数据很关键,所以它将使用安全写入保存,计数器等将使用不安全写入保存。这种基于数据重要性和写入密集度的策略是否正确?

  3. 与 MySQL 相比,监控、备份和恢复 MongoDB 有多容易?我们需要计划定期备份(比如每天),并在发生灾难时轻松恢复它们。我对 MongoDB 的最佳选择是什么,以使其成为应用程序的安全选择。

稳定性、备份、快照、恢复、更广泛的采用 Ieddatabase 持久性是指向我使用 MySQL 作为 RDBMS+NoSql 的原因,即使 NoSQL 文档存储可以更好地服务于我的目的。

考虑到我想到的数据库设计,请将您的观点集中在 MySQL 和 MongoDB 之间的选择上。我知道可能有更好的方法来使用 RDBMS 或 MongoDB 文档来规划数据库设计。但这不是我当前问题的重点。

更新:从 MySQL 5.7 开始,MySQL 支持丰富的原生 JSON 数据类型,提供数据灵活性以及丰富的 JSON 查询。

https://dev.mysql.com/doc/refman/5.7/en/json.html

4

3 回答 3

22

所以,直接回答问题...

如果一半数据是无模式的,我们是否应该选择 mongodb,如果使用 MySQL,我们应该将其存储为 JSON 吗?

无模式存储无疑是使用 MongoDB 的一个令人信服的理由,但正如您所指出的,将 JSON 存储在 RDBMS 中也相当容易。MongoDB 的强大之处在于对无模式存储的丰富查询。

如果我可以指出插图中关于更新 JSON 字段的一个小缺陷,那么这不仅仅是获取当前值、更新文档然后将其推回数据库的问题。该过程必须全部包含在事务中。在您开始对数据库进行非规范化之前,事务往往相当简单。然后像记录赞成票这样简单的事情可以锁定整个架构中的表。

使用 MongoDB,没有事务。但是操作几乎总是可以以允许原子更新的方式构造。这通常涉及 SQL 范式的一些戏剧性转变,但在我看来,一旦您停止尝试将对象强制放入表中,它们就相当明显了。至少,很多其他人也遇到了你将面临的同样问题,而且 Mongo 社区往往相当开放,并且对他们所克服的挑战直言不讳。

像主帖这样的一些数据是关键的,所以它将使用安全写入保存,计数器等将使用不安全写入保存。这种基于数据重要性和写入密集度的策略是否正确?

通过“安全写入”,我假设您的意思是在每次写入后打开自动“getLastError()”的选项。我们对 DBCollection 有一个非常薄的包装器,它允许我们对何时调用 getLastError() 进行细粒度控制。但是,我们的策略不是基于数据的“重要程度”,而是基于查询之后的代码是否期望任何修改在接下来的读取中立即可见。

一般来说,这仍然是一个糟糕的指标,我们已经迁移到 findAndModify() 以获得相同的行为。在我们仍然显式调用 getLastError() 的情况下,数据库可能会拒绝写入,例如当我们 insert() 的 _id 可能重复时。

与 mysql 相比,Mongodb 的监控、备份和恢复有多容易?我们需要计划定期备份(比如每天),并在发生灾难时轻松恢复它们。我对 mongoDb 有哪些最佳选择,以使其成为应用程序的安全选择?

恐怕我不能谈论我们的备份/恢复策略是否有效,因为我们还没有恢复。我们遵循 MongoDB 备份建议;@mark-hillick 在总结这些方面做得很好。我们正在使用副本集,我们已经迁移了 MongoDB 版本并引入了新的副本成员。到目前为止,我们还没有停机时间,所以我不确定我能不能说得好。

稳定性、备份、快照、恢复、更广泛的采用 iedatabase 持久性是指向我使用 MySQL 作为 RDBMS+NoSql 的原因,即使 NoSQL 文档存储可以更好地服务于我的目的。

因此,根据我的经验,MongoDB 通过一组足够丰富的查询原语来存储无模式数据,以至于事务通常可以被原子操作替换。忘记 10 多年的 SQL 经验是很困难的,但我遇到的每个问题都已由社区或 10gen 直接解决。我记得我们没有丢失数据或有任何停机时间。

简单来说,就查询、维护、可扩展性和可靠性而言,MongoDB 是我用过的最好的数据存储生态系统。除非我有一个非常明确的关系应用程序,以至于我良心上只能使用 SQL 以外的任何东西,否则我会尽一切努力使用 MongoDB。

我不为 10gen 工作,但我非常感谢那些工作的人。

于 2012-10-22T22:25:57.233 回答
13

我不会对这些比较发表评论(我为 10gen 工作,我觉得这样做不合适),但是,我会回答具体的 MongoDB 问题,以便您更好地做出决定。

备份

这里的文档非常详尽,涵盖了很多方面:

  • 块级方法(LVM 让它变得非常简单,很多人都这样做)
  • 有/没有日志
  • EBS 快照
  • 一般快照
  • 复制(技术上不是备份,但是,很多人使用副本集来进行冗余和备份 - 不推荐这样做,但已经完成)

直到最近,还没有 MongoDB 等价物,mylvmbackup但一个好人写了一个 :) 用他的话来说

到目前为止的早期阶段:它只是一个美化的 shell 脚本,需要更多的错误检查。但它已经对我有用,我想我会分享快乐。欢迎提交错误报告、补丁和建议。

从这里获取一份副本。

恢复

mongodump完全记录在这里,mongorestore 在这里

mongodump将不包含索引,但包含 system.indexes 集合,因此 mongorestore 可以在您恢复 bson 文件时重建索引。bson 文件是实际数据,mongoexport/mongoimport但不是类型安全的,所以它可以是任何东西(从技术上讲):)

监控

记录在这里

我喜欢 Cacti,但是 afaik,Cacti 模板没有跟上 MongoDB 的变化,所以依赖旧语法,所以发布 2.0.4,我相信有问题。

Nagios 运行良好,但它是 Nagios,所以你要么爱要么恨它。很多人使用 Nagios,它似乎为他们提供了很好的可见性。

我听说有人在看 Zappix,但我从未使用过它,所以无法发表评论。

此外,您还可以使用免费的外部托管彩信。您的 MongoDB 实例运行一个代理,其中一个代理通过 https 与 mms.10gen.com 进行通信(使用 python 代码)。我们使用 MMS 来查看有关 MongoDB 实例的所有性能统计信息,这从高层次的广泛视图以及提供向下钻取的能力非常有益。它安装简单,您无需为此运行任何硬件。许多客户运行它,有些客户用 Cacti/Nagios 来称赞它。

可以在此处找到有关 MMS 的帮助信息(这是一份非常详细、内容丰富的文档)。

于 2012-10-17T16:08:01.820 回答
5

存储 json 的 mysql 解决方案的缺点之一是您将无法有效地搜索 json 数据。如果将其全部存储在 mongodb 中,则可以对包括 json 在内的所有数据创建索引和/或查询。

Mongo 的编写工作非常好,与 mysql 相比,你唯一失去的就是事务支持,因此回滚多部分保存的能力。但是,如果您能够在原子操作中提交您的更改,那么就不存在数据安全问题。如果你被复制了,mongo 提供了一个“最终一致”的承诺,这样从服务器最终将镜像主服务器。

Mongodb 不提供某些 db 结构(如外键)的本地强制或级联,因此您必须自己管理这些(例如通过组合,这是 mongo 的优势之一),或通过使用 dbrefs。

如果您确实需要事务支持和强大的“安全”写入,但仍需要 nosql 提供的灵活性,您可以考虑使用混合解决方案。这将允许您使用 mysql 作为您的主要帖子存储,然后使用 mongodb 作为您的“无模式”存储。这是一个讨论混合 mongo/rdbms 解决方案的文档的链接: http://www.10gen.com/events/hybrid-applications 这篇文章来自 10gen 的站点,但是您可以通过快速的 google 搜索找到其他示例。

2019 年 5 月 28 日更新

自发布此答案以来,MySQL 和 Mongodb 都发生了许多变化,因此它们之间的优缺点变得更加模糊。此更新对原始问题并没有真正的帮助,但我这样做是为了确保任何新读者都能获得更新的信息。

MongoDB 现在支持事务: https ://docs.mongodb.com/manual/core/transactions/

MySql 现在支持索引和搜索 json 字段: https ://dev.mysql.com/doc/refman/5.7/en/json.html

于 2012-10-22T21:21:17.543 回答