gpt4 book ai didi

java - CouchDB/Couchbase/MongoDB 事务模拟?

转载 作者:行者123 更新时间:2023-11-29 07:46:01 27 4
gpt4 key购买 nike

我以前从未使用过 CouchDB/MongoDB/Couchbase,现在正在为我的应用程序评估它们。总的来说,它们似乎是我想使用的非常有趣的技术。然而,由于有 RDBMS 背景,我对缺少事务感到厌烦。但与此同时,我知道考虑到数据的组织方式,对事务的需求将大大减少,就像我在 RDBMS 中所需要的那样。

话虽如此,我有以下要求,但不确定是否/如何使用 NoSQL 数据库。

  1. 我有一份客户名单
  2. 每个客户端可以有多个文件
  3. 每个文件必须为特定客户按顺序编号

给定 RDBMS,这将相当简单。一张表用于客户端,一张(或多张)用于文件。在客户表中,保留一个最后一个文件编号的计数器,并在向文件表中插入新记录时递增 1。将所有内容包装在一个事务中,您就可以确信不会存在不一致。哎呀,为了安全起见,我什至可以在 (clientId, filenumber) 索引上设置唯一约束,以确保永远不会为客户端使用两次相同的文件号。

我怎样才能在 MongoDB 或 CouchDB/base 中完成类似的事情?它甚至可行吗?我一直在阅读有关两阶段提交的信息,但我似乎无法理解在这种情况下它是如何工作的。 Spring/Java 中是否有任何东西可以提供适用于这些数据库的两阶段提交,或者它是否需要自定义代码?

最佳答案

Couchdb 默认是事务性的。 couchdb 中的每个文档都包含一个 _rev 键。对文档的所有更新都是针对此 _rev 键执行的:-

  1. 获取文档。
  2. 使用 _rev 属性发送它进行更新。
  3. 如果更新成功,那么您已经更新了文档的最新 _rev
  4. 如果更新失败,文档不是最新的。重复步骤 1-3。

查看 this answer by MrKurt以获得更详细的解释。

couchdb recipies有一个银行示例,展示了如何在 couchdb 中完成交易。

还有这个atomic bank transfers说明 couchdb 中事务的文章。

无论如何,所有这些链接的共同主题是,如果您遵循针对 _rev 进行更新的 couchdb 模式,您的数据库中就不会出现不一致的状态。

Heck, just to be safe, I could even put a unique constraint on a (clientId, filenumber) index to ensure that there is never the same filenumber used twice for a client.

所有 couchdb 文档都是唯一的,因为两个文档中的 _id 字段不能相同。查看view cookbook

This is an easy one: within a CouchDB database, each document must have a unique _id field. If you require unique values in a database, just assign them to a document’s _id field and CouchDB will enforce uniqueness for you.

There’s one caveat, though: in the distributed case, when you are running more than one CouchDB node that accepts write requests, uniqueness can be guaranteed only per node or outside of CouchDB. CouchDB will allow two identical IDs to be written to two different nodes. On replication, CouchDB will detect a conflict and flag the document accordingly.

根据评论编辑

In a case where you want to increment a field in one document based on the successful insert of another document

在这种情况下,您可以使用单独的文档。你插入一个文件,等待成功响应。然后添加另一个文档,如

{_id:'some_id','count':1}

有了它,您可以设置一个 map reduce View ,它只计算这些文档的结果,并且您有一个更新计数器。您所做的只是插入一个新文档以反射(reflect)插入成功,而不是为更新更新单个文档。

I always end up with the case where a failed file insert would leave the DB in an inconsistent state especially with another client successfully inserting a file at the same time.

好的,我已经描述了如何对单独的文档进行更新,但即使更新单个文档,您也可以避免不一致,如果您:

  1. 插入一个新文件
  2. 当 couchdb 给出成功消息时 -> 尝试更新计数器。

为什么这有效?

这是可行的,因为当您尝试更新 update document 时,您必须提供 _rev 字符串。您可以将 _rev 视为文档的本地状态。考虑这种情况:-

  1. 您阅读了要更新的文档。
  2. 您更改了一些字段。
  3. 与此同时,另一个请求已经更改了原始文档。这意味着文档现在有一个新的 _rev
  4. 但是您请求 couchdb 使用您在步骤 #1 中读取的陈旧_rev 更新文档。
  5. Couchdb 将生成异常。
  6. 您再次阅读文档获取最新的 _rev 并尝试更新它。

因此,如果您这样做,您将始终需要根据文档的最新版本进行更新。我希望这能让事情变得更清楚一些。

注意:

正如 Daniel 所指出的,_rev 规则不适用于批量更新。

关于java - CouchDB/Couchbase/MongoDB 事务模拟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25735979/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com