NoSQL中的事务?


77

我正在寻找NoSQL来扩展数据库的替代方案。如果我想要对此类事物敏感的基于事务的事物,该怎么办?


3
仅供参考... NoSQL数据库仍然是DB,它们只是不相关的。对于事务,事务只是查询和更新的逻辑分组。非关系数据库仍然提供这两个功能。什么样的事物对什么事物敏感?
joejoeson 2010年

1
好吧,我想进行货币交易,或者至少考虑一下。但是我仍然想要某种意义上的完整性。
蒂米” 2010年

3
您有多少TB的数据无法使用具有内置事务支持的标准主流RDBMS?
gbn

@gbn数据的TB数量与使用NoSQL DB无关。也许他想摆脱关系数据库中的EAV模型。
2016年

Answers:


41

一般而言,NoSQL解决方案的事务语义比关系数据库更轻巧,但在某种程度上仍具有原子操作的便利。

通常,执行主-主复制的服务器提供的一致性较少,而可用性更高。因此,应该为正确的问题选择正确的工具。

许多提供单个文档(或行等)级别的事务。例如,在MongoDB中,单个文档具有原子性-但是文档可以相当丰富,因此通常可以很好地工作-在此处提供更多信息。


5
一些NoSQL数据库,例如MarkLogic,实际上提供了真正的ACID事务。
埃里克·布洛赫

5
RavenDB还提供真实的ACID事务。
马特·约翰逊·品脱

5
FoundationDB还提供了多节点集群中的多密钥ACID事务。
2013年

5
Neo4j是NoSQL存储,并提供ACID属性。
Nadjib Mami 2014年

3
RavenDB不提供真正的ACID事务。它使用一种称为“快照隔离”的弱隔离形式。它通过外部协调员提供全球交易,但不鼓励使用foundationdb.com/acid-claims
山本彰(Akira Yamamoto)

18

这是我发现的最接近的答案,适用于任何NoSQL数据库。它在Heroku.com的Adam Wiggins的2007年博客文章中:

使用数据库事务来将资金从一个银行帐户转移到另一个银行帐户的旧示例是“总牛市”。正确的解决方案是存储分类帐事件的列表(帐户之间的转帐),并将当前余额显示为分类帐的总和。如果您使用功能性语言编程(或以这种方式思考),这是显而易见的。

来自:http : //adam.heroku.com/past/2007/12/17/a_world_without_sql/(他的网站非常适合可扩展性方面的想法。)

我将以上段落解释为:

  1. 为会员帐户创建数据库。
  2. 创建一个消息队列。昵称“分类帐”。
  3. 添加后台工作人员来满足队列中的每个请求。

更多信息。在队列/后台工作者上:http : //adam.heroku.com/past/2009/4/14/building_a_queuebacked_feed_reader_part_1/

客户(又名会员或客户)按照以下步骤提取资金:

  1. 提出提款要求。
  2. 请求发送到服务器。
  3. 服务器将其放入队列中。消息是:“拿出$ 5,000。”
  4. 客户端显示:“请稍候,正在处理请求...”
  5. 客户端计算机每2秒轮询一次服务器,询问“请求是否已完成?”
  6. 在服务器上,后台工作人员正在以先进先出的方式满足其他成员的先前请求。最终,他们得到您客户的要求取出钱。
  7. 完成请求后,将向客户发送一条带有新余额的消息。

如果您对Node.js或Ruby / Rack感到满意,则可以使用Heroku.com快速创建一个小型模型。

总的想法似乎很容易,并且比使用数据库中难于扩展的事务更好。

免责声明:我尚未以任何方式实施此操作。我出于好奇而阅读了这些内容,尽管我实际上并不需要它们。是的,@ gbn是对的,带有事务的RDBMS可能足以满足Timmy和我的需要。不过,很高兴看到您可以使用开源工具和一个名为“ Razorblades的龙卷风”的入门网站将NoSQL数据库带到多远。


35
对于交易的“ hello world”示例似乎是一种奇怪的批评。如果在创建“分类帐事件”之一期间失败了怎么办?那么该帐户的余额将是错误的。对于我来说,这听起来不可行。
a_horse_with_no_name

21
链接的网页显示出对几乎所有金融系统都必须使用ACID的无知程度。首先,本文主张“绩效”,而忽略了必须从历史中读取每个交易来处理新交易的性能成本。其次,更重要的是,当同一帐户上发生并发请求,并且业务交易包含对多个实体的更新时,该解决方案如何工作?如果服务器在处理过程中死亡,该怎么办?
安德鲁不是圣徒

2
这都是关于两阶段提交的。到处都是Google,您会发现无需交易即可保持一致性。
2012年

2
安德鲁,如果您的卡交易中途失败,会发生什么。您是否见过带有反向交易的银行对账单?
阿利斯泰尔

16

NoSQL涵盖了各种各样的工具和服务,包括键值,文档,图形和大列存储。他们通常尝试通过分布数据处理来提高数据存储的可伸缩性。事务需要数据库如何执行用户操作的ACID属性。ACID限制了如何提高可伸缩性:大多数NoSQL工具放宽了操作的一致性标准,以获取容错性和可扩展性,这使得实施ACID事务非常困难。

CAP定理通常被认为是分布式数据存储的理论依据:一致性,可用性和分区容忍性不能同时实现。SQL,NoSQL和NewSQL工具可以根据它们放弃的方式进行分类。在这里可以找到一个好身材。

代替ACID的一组新的,较弱的需求是BASE(“基本上可用的,软状态,最终的一致性”)。但是,最终一致的工具(“最终对项目的所有访问将返回最后更新的值”)在银行等交易应用程序中几乎是不可接受的。这里的一个好主意是使用内存中,面向列的分布式SQL / ACID数据库,例如VoltDB;我建议查看这些“ NewSQL”解决方案。


“这些工具大多数都放弃了一致性,因此放弃了ACID”。接缝中,您混淆了ACID中的一致性和CAP中的一致性。CAP中的C表示数据的所有副本均相等。虽然ACID中的C是一个模糊且含糊的术语,但是...一般而言,可用性与ACID并不矛盾。Google Spinner的例子证明了这一点。
阿列克谢

ACID一致性要求事务,因为一系列客户端操作只能源自有效数据库状态并以有效数据库状态结束。它仅与CAP中的C类似,所以没错,它们并不相同并且不矛盾。在AP系统中实现ACID事务非常困难,通常认为这是可伸缩性。我改一下我的答案。现在回首,我发现CAP定理和CAP类别过于模糊,在分类这些工具时没有提供真正的帮助。我认为CAP仅是分布式系统设计折衷的一个有趣的理论示例。
csaba

13

只是想评论此线程上的货币交易建议。交易是您真正想与转帐一起使用的东西。

给出的如何进行传输的示例非常整洁。

但是在现实生活中,转帐可能包括向其他帐户收费或付款。人们会因使用来自其他帐户的某些卡而获得奖金,或者他们可能会从其帐户收取的费用转至同一系统中的另一个帐户。费用或付款可能因金融交易而异,您可能需要保持簿记系统,该系统会在每次交易发生时显示其贷方和借方。

这意味着您要同时更新多个行,因为可以从一个或多个帐户上借记一个帐户的贷方。首先,您锁定行,以便在更新之前不能进行任何更改,然后确保写入的数据与事务一致。

这就是为什么您真正想要使用事务的原因。如果在写入一行时出现任何问题,则可以回滚整个更新,而不会导致财务交易数据不一致。


1
还有其他可能更好的方法来处理交易的副作用。事务是原始事件,只要它是原子记录的,任何其他错误或问题都可以追溯到该事件。
克里斯·尼古拉

6

一笔交易和两项操作(例如一笔支付5,000美元,第二笔收取5,000美元)的问题是您有两个优先级相同的帐户。您不能使用一个帐户来确认第二个帐户(或以相反的顺序)。在这种情况下,您只能保证一个帐户是正确的(已确认),第二个帐户(确认)可能会失败。让我们看一下它为什么会失败(使用消息提示,发送者被接收者确认):

  1. 向收款人账户写入+ $ 5,000
  2. 如果成功-向发件人帐户写入$ 5,000
  3. 如果失败,请重试或取消或显示消息

它将保证除了#1。但是,如果#2失败了,谁能保证?反向顺序相同。

但这可以实现没有事务和NoSQL的安全。始终允许您使用将由发送方和接收方确认的第三实体,并保证已执行您的操作:

  1. 生成唯一的交易ID并创建交易实体
  2. 向收款人账户写+5,000美元(参考交易ID)
  3. 如果成功-设置要发送的交易状态
  4. 向sedned帐户写入-$ 5,000(参考交易ID)
  5. 如果成功-设置要接收的交易状态

此交易记录将确保可以发送/接收消息。现在,您可以按事务ID检查每条消息,以及它的状态是否已收到或已完成-您可以考虑将其用于用户余额。


1
如果步骤3和5失败了怎么办?这增加了很多复杂性,这就是数据库事务如此有用的原因。
技能M2

通常,这样的系统从不仅仅依靠sql功能来验证事务。而且在实际情况下,贷记和借记大多是跨时间和银行发生的,这超出了sql或nosql的功能...此类问题只能由设计良好的体系结构来照顾,该体系结构可以在系统内或跨系统的事务中顺利运行系统。
卡佩什·波帕特

我认为这种方法很好。但是,我们还必须考虑分布式执行事务部分(一部分运行在例如微服务1中,另一部分运行在例如微服务2中,该部分在云中不同域中的服务器上运行) )。如果没有某种后台工作来通过适当地设置驻留在多个服务器中的关联记录的状态来处理这些事务,那么NoSQL中的分布式事务就很难做到(但不可避免)。
普拉萨德


1

您始终可以在SQL DB中使用NoSQL方法。NoSQL似乎通常使用“键/值数据存储”:您始终可以在首选的RDBMS中实施此操作,从而保留诸如事务,ACID属性,友好的DBA的支持之类的好东西,同时实现NoSQL的性能和灵活性优势,例如通过诸如

CREATE TABLE MY_KEY_VALUE_DATA
(
    id_content INTEGER PRIMARY KEY,
    b_content  BLOB
);

值得一提的是,您可以在此处添加额外的字段,以将您的内容链接到其他适当关系的表中,同时仍将大容量内容保留在主BLOB(或TEXT,如果适用)字段中。

我个人比较喜欢TEXT表示形式,因此您不会被用于处理数据的语言所束缚,例如,使用序列化Java意味着您可以从Perl访问内容进行报告。TEXT也更易于调试,通常可以作为开发人员来使用。



1

这就是为什么我要创建NoSQL文档存储解决方案,以便能够借助非结构化数据方法在企业应用程序上使用“真实”事务。请访问http://djondb.com,并随意添加您认为可能有用的任何功能。



0

如果NoSQL解决方案支持比较设置,则可以在其之上实现乐观交易。我在GitHub页面上写了一个示例和一些说明,以了解如何在MongoDB中执行此操作,但是您可以在任何合适的NoSQL解决方案中重复进行此操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.