使用NoSQL对非分布式系统有意义吗? (试图理解最终的一致性)

时间:2011-09-25 16:13:39

标签: mongodb performance couchdb eventual-consistency nosql

过去两天我一直在阅读和学习NoSQL和MongoDB,CouchDB等,但我仍然无法判断这是否适合我。

令我担心的是最终的一致性。在使用集群时,这种一致性是否只会起作用? (我在一个专用服务器上托管我的网站,所以我不知道我是否可以从NoSQL中受益)对于哪种应用程序可以最终保持一致(而不是ACID),以及哪些应用程序不是T'你能举个例子吗?在应用程序中可能发生的最糟糕的事情是什么,可以最终保持一致性?

我读到的另一件事是MongoDB在内存中保留了很多东西。在文档中,它描述了一些有2GB数据限制的32位系统。那是因为32位系统的ram限制吗?

3 个答案:

答案 0 :(得分:5)

我只能说CouchDB,但没有必要在最终一致性和ACID之间做出选择,它们不属于同一类别。

CouchDB完全是ACID。文档更新是原子的,一致的,隔离的和持久的(使用CouchDB建议的delayed_commits = false的生产设置,在返回201成功代码之前,您的更新将刷新到磁盘)。 提供的CouchDB所做的是多项交易(因为当项目存储在不同的服务器中时,这些交易非常难以扩展)。 “交易”和“ACID”之间的混淆是令人遗憾但可以原谅的,因为典型的RDBMS通常都支持这两者。

最终的一致性是关于数据库副本如何聚合在同一数据集上。考虑传统RDBMS中的主从设置。该关系的一些配置将使用分布式事务机制,使得主服务器和从服务器始终处于锁定步骤。但是,出于性能原因,通常会放松它。主设备可以在本地进行交易,然后通过交易日志将它们懒洋洋地转发给奴隶。这也是“最终一致性”,当日志完全耗尽时,两台服务器将汇聚在同一数据集上。 CouchDB更进一步,消除了主设备和从设备之间的区别。也就是说,CouchDB服务器可以被视为相等的对等体,任何主机上的更改都可以正确地复制到其他主机上。

最终一致性的技巧是如何处理不同主机上相同项目的更新。在CouchDB中,这些单独的更新在同一项上被检测为“冲突”,并且复制可确保所有主机上都存在所有冲突更新。然后CouchDB选择其中一个作为当前版本。可以通过删除不想保留的冲突来修改此选择。

答案 1 :(得分:4)

  • 过去两天我一直在阅读和学习NoSQL和MongoDB,CouchDB等,但我仍然无法判断这是否适合我。 < / LI>

NoSQL数据库解决了传统RDMS难以解决的set of problems问题。如果您的任何问题都在该集合中,NoSQL可以是the right storage for you

  • 使用群集时,最终的一致性是否会启动?

可能读取返回刚刚保留的数据的不同/以前版本的数据时,最终的一致性会“开始”。例如:

您将相同的数据保存到 MORE THAN ONE 位置,让我们说A和B.根据配置的不同,持久化操作可能仅在持久化到A之后返回(而不是仅仅B但)。在那之后你从B中读取了那些尚未存在的数据。 最终它会在那里,但遗憾的是当你读回来时

  • 对于哪种应用程序,最终可以保持最终的一致性(而不是ACID),哪些应用程序不是?

NOT OK =&gt;您有一个家庭银行帐户,有100美元可用。现在你和你的配偶试图在100美元的同时(在不同的商店)买东西。如果银行用“最终一致性”模型实现了这一点,例如,在多个节点上,你的配偶可能在花费了所有这些节点后花了100美元几毫秒。这对银行来说不是一个好日子。

OK =&gt;你有Twitter上的10000粉丝。你发推文“嘿,谁今晚要做一些黑客攻击?”。 100%的一致性意味着所有10000人将同时收到您的邀请。但是,如果约翰在玛丽做了2秒之后看到你的推文,那么真的不会发生。

  • 在应用程序中可能发生的最糟糕的事情是什么,以确保最终的一致性?

例如:当节点A获取数据时,节点B获得相同的数据[它们是同步的]。如果NoSQL解决方案是可靠的,那将是更糟糕的事情。

  • 我读到的另一件事是MongoDB在内存中保留了很多东西。在文档中,它描述了一些有2GB数据限制的32位系统。那是因为32位系统的ram限制吗?

来自MongoDB docs:

MongoDB是一个在Linux,Windows和OS X上运行的服务器进程。它可以作为32位或64位应用程序运行。我们建议以64位模式运行,因为Mongo仅限于32位模式下所有数据库的总数据大小约为2GB。

答案 2 :(得分:1)

Brewers CAP theorem是了解哪些选项适合您的最佳来源。我可以说这一切都取决于但是如果我们谈论Mongo那么它提供了开箱即用的水平可伸缩性,并且在某些情况下总是很好。

现在关于一致性。实际上,您有三种方法可以保持数据的最新状态:

1)首先要考虑的是“安全”模式或“getLastError()”,如Andreas所示。如果发出“安全”写入,则表示数据库已收到插入并应用了写入。但是,MongoDB每60秒只刷新一次磁盘,因此服务器可能会在没有磁盘数据的情况下发生故障。

2)要考虑的第二件事是“日记”(v1.8 +)。打开日记功能后,每隔100毫秒将数据刷新到日志。所以你在失败之前有一个较小的时间窗口。驱动程序有一个“fsync”选项(检查该名称)比“安全”更进一步,它等待确认数据已被刷新到磁盘(即日志文件)。但是,这仅涵盖一台服务器。如果服务器上的硬盘刚刚死掉会怎么样?那么你需要第二份副本。

3)要考虑的第三件事是复制。在返回之前,驱动程序支持“W”参数,该参数表示“将此数据复制到N个节点”。如果写入在某个超时之前没有到达“N”节点,则写入失败(抛出异常)。但是,您必须根据副本集中的节点数正确配置“W”。同样,因为硬盘驱动器可能会失败,即使使用日记功能,您也会想要查看复制。然后是跨数据中心的复制,这太长了,无法进入这里。最后要考虑的是你需要“回滚”。根据我的理解,MongoDB没有这种“回滚”能力。如果您正在进行批量插入,那么您将获得的最佳结果是指示哪些元素失败。

无论如何,当数据一致性成为开发人员的责任时,有很多场景需要注意并包括所有场景并调整数据库架构,因为没有“这是正确的方法” Mongo就像我们习惯于RDB-s。

关于内存 - 这完全是一个性能问题,MongoDB将索引和“工作集”保存在RAM中。通过限制RAM来限制工作集。实际上你可以拥有一块SSD和更少的RAM,而不是大量的RAM和一块硬盘 - 至少这些是官方建议。无论如何这个问题都是个人问题,你应该针对你的特定用例进行性能测试