Transactions NoSQL-建模RDBMS事务读取

Transactions NoSQL-建模RDBMS事务读取,transactions,nosql,Transactions,Nosql,通常,NoSQL数据库不提供保证完全成功或失败的RDBMS类型的事务。我知道有些人是这样做的,但我有兴趣探索他们没有的情况。然而,NoSQL提供者很快就指出,需要在传统RDBMS数据库中进行事务处理的行为可以在原子NoSQL操作(即单文档写入)中完成。例如,这里有一个-在RDBMS中,您编写一个描述传输的新文档,而不是在事务中减少一个余额并增加另外两个写入 但是,在RDBMS事务中进行此类传输可能涉及三个操作: 验证发送方的当前余额是否足以转账,如果是: 减少发送方余额 增加收款人余额 当处理两

通常,NoSQL数据库不提供保证完全成功或失败的RDBMS类型的事务。我知道有些人是这样做的,但我有兴趣探索他们没有的情况。然而,NoSQL提供者很快就指出,需要在传统RDBMS数据库中进行事务处理的行为可以在原子NoSQL操作(即单文档写入)中完成。例如,这里有一个-在RDBMS中,您编写一个描述传输的新文档,而不是在事务中减少一个余额并增加另外两个写入

但是,在RDBMS事务中进行此类传输可能涉及三个操作:

验证发送方的当前余额是否足以转账,如果是: 减少发送方余额 增加收款人余额 当处理两次付款时,两次付款都试图从只能支付其中一次或另一次的帐户中提取资金,我们如何在NoSQL环境中进行管理,并确保我们不会透支?当两个操作试图更新同一文档时,NoSQL数据库通常有一种机制来检测和防止写冲突。但是,由于编写文档来描述转账的方法意味着编写新文档,因此无法检测到同时发生的两次付款

这里有一个明显的漏洞,就是使用代码锁来防止两次支付在应用程序级别同时开始,但我感兴趣的是,是否有一种合理的无锁方法来检查一个值,然后修改它,以防止并发操作将该值置于无效状态

我想出了两种方法来实现这个目标,但由于这样或那样的原因,这两种方法都令人不快——我很感兴趣的是,是否有我错过的更整洁的解决方案。为了一个有用的比喻,我将用平衡转移来描述它们。假设Alice试图同时支付Bob和Charlie,但只能支付其中一个

简单地用一个文档进行操作,每次写入一个文档,如果我们最终透支了,则进行反向操作 简单地把这两个付款通过。每次付款后,检查Alice是否透支。这里的问题是,两种支付方式都有可能发现透支并收回。如果他们都在这一点上放弃,双方都不会成功。如果他们都在退出后再次检查余额,他们可能都会发现有足够的钱再试一次,而且他们可以这样做。循环继续。这最终可以通过随机回退延迟来解决,但这会给应用程序带来负担,使其无法以相对复杂的方式管理重试,并且还会留下一长串失败的支付。 也有可能,如果有人在这期间将资金转入Alice的帐户,那么两次付款实际上都会成功。爱丽丝本来会被透支一段时间,但现在却身无分文。这可能是可以接受的,也可能是不可以接受的

与其为每次付款编写新文档,不如将其附加到单个文档中 通过这种方式,我们可以使用写入冲突检测来强制一个付款重试。然而,我们附加到的文档将很快变得非常大,我们也放弃了对付款进行索引的能力


在我看来,抛开供应商索赔不谈,对于这样的应用程序,RDBMS可能仍然是最好的工作工具。

至少在英国,在这种情况下,Alice只会进行未经授权的透支,如果在工作日结束前未对余额进行排序,她将受到处罚。我认为你真的需要考虑你是否真的需要原子交易到这个水平。我发现很难想出比CouchDB更复杂的例子了,因为CouchDB很好用。金融交易的东西实际上只是一个挂起问题的例子。但在很多类似的情况下,透支都不是一种选择——比如说,你不能在你的蒸汽钱包或任何使用虚拟货币的东西上透支。