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



我一直在阅读和学习关于NoSQL和MongoDB, CouchDB等,在过去的两天里,但我仍然不能告诉这是否是适合我的存储类型。

让我担心的是最终的一致性。这种一致性是否只在使用集群时才会出现?(我把我的站点托管在一个单独的专用服务器上,所以我不知道我是否可以从NoSQL中受益)对于哪种类型的应用程序可以有最终的一致性(而不是ACID),对于哪些应用程序不可以?你能给我举几个例子吗?在一个可以实现最终一致性的应用程序中可能发生的最糟糕的事情是什么?

我读到的另一件事是MongoDB在内存中保留了很多东西。文档中提到32位系统有2gb的数据限制。这是因为32位系统的内存限制吗?

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

CouchDB是完全ACID的。文档更新是原子的、一致的、隔离的和持久的(使用CouchDB推荐的产品设置delayed_commits=false,在返回201成功代码之前将更新刷新到磁盘)。CouchDB 没有提供的是多项目事务(因为当项目存储在单独的服务器中时,这些事务很难扩展)。"transaction"one_answers"ACID"之间的混淆是令人遗憾的,但也可以原谅,因为典型的RDBMS通常都支持这两个。

最终一致性是关于数据库副本如何在相同的数据集上收敛。考虑一下传统RDBMS中的主从设置。该关系的某些配置将使用分布式事务机制,这样主从关系总是处于锁步状态。但是,出于性能原因,通常会放宽此限制。主服务器可以在本地创建事务,然后通过事务日志将它们惰性地转发给从服务器。这也是"最终一致性",当日志完全耗尽时,两个服务器将集中在相同的数据集上。CouchDB更进一步,消除了主从之间的区别。也就是说,可以将CouchDB服务器视为平等的对等节点,在任何主机上所做的更改都可以正确地复制到其他主机上。

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

  • 我一直在阅读和学习关于NoSQL和MongoDB, CouchDB等,在过去的两天,但我仍然不能告诉如果这是适合我的存储类型。

NoSQL数据库解决了一系列传统RDMS难以解决的问题。NoSQL可以是the right storage for you,如果你的任何问题都在这个集合中。

  • 最终一致性只有在使用集群时才会生效吗?
读取返回的数据与刚刚持久化的数据不同/以前的版本时,

最终一致性"开始"。例如:

您将相同的数据块持久化到多于一个位置,假设是A和B。根据配置,持久化操作可能只在持久化到A之后返回(现在还不是B)。在那之后,你从B中读取数据,它还没有在那里。最终它会在那里,但不幸的是,当你读回来的时候,它不在那里

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

NOT OK =>你有一个家庭银行账户,有100美元可用。现在你和你的配偶试图在同一时间(在不同的商店)花100美元买东西。如果银行用"最终一致性"模型来实现这一点,例如,在多个节点上,你的配偶可能在你花完100美元的几毫秒后才花完100美元。这可不是银行的好日子。

OK =>你在Twitter上有10000个粉丝。你发推特说"今晚谁想来点黑客活动"100%的一致性意味着所有10000人都会同时收到你的邀请。但如果约翰比玛丽晚两秒看到你的推特,就不会发生什么坏事。

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

巨大的延迟,例如当节点A获得数据时,节点B获得相同的数据[它们是同步的]。如果NoSQL解决方案是可靠的,那将是可能发生的最糟糕的事情。

  • 我读到的另一件事是MongoDB在内存中保留了很多东西。文档中提到32位系统有2gb的数据限制。这是因为32位系统的内存限制吗?
from MongoDB docs:

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

Brewers CAP定理是了解您可用的选项的最佳来源。我可以说这要看情况,但如果我们谈论Mongo,它提供了开箱即用的水平可扩展性,在某些情况下它总是很好。

现在谈谈一致性。实际上,您有三个选项来保持数据最新:

1)首先要考虑的是"安全"模式或"getLastError()",正如Andreas所指出的。如果发出"安全"写操作,就知道数据库已经接收到插入操作并应用了写操作。但是,MongoDB每60秒才刷新一次磁盘,因此如果没有磁盘上的数据,服务器可能会失败。

2)第二件要考虑的事情是"日志记录"(v1.8+)。启用日志记录后,每隔100毫秒就会将数据刷新到日志中。所以在失败之前你有一个更小的时间窗口。驱动程序有一个"fsync"选项(检查名称),它比"安全"更进一步,它等待确认数据已被刷新到磁盘(即日志文件)。但是,这只涉及一台服务器。如果服务器上的硬盘没电了怎么办?好吧,你需要一份副本。

第三件要考虑的事情是复制。驱动程序支持一个"W"参数,表示在返回之前"将此数据复制到N个节点"。如果在某个超时之前写操作没有到达"N"个节点,则写操作失败(抛出异常)。但是,您必须根据副本集中的节点数量正确配置"W"。同样,由于硬盘驱动器可能出现故障,即使有日志记录,您也需要查看复制情况。然后是跨数据中心的复制,这里讲得太长了。最后要考虑的是"回滚"的需求。从我的理解,MongoDB没有这种"回滚"的能力。如果您正在进行批量插入,您将得到的最好结果是哪些元素失败的指示。

无论如何,在很多情况下,数据一致性成为开发人员的责任,这取决于你要小心,包括所有的场景和调整DB模式,因为在mongodb中没有"这是正确的方法",就像我们在RDB-s中习惯的那样。

关于内存-这完全是一个性能问题,MongoDB在RAM中保持索引和"工作集"。通过限制你的内存,你也限制了你的工作集。实际上,你可以有一个SSD和少量的RAM,而不是大量的RAM和一个HDD——至少这是官方的建议。无论如何,这个问题是独立的,您应该针对您的特定用例进行性能测试

最新更新