微服务和事务管理器如何处理并发问题

问题描述 投票:0回答:3

我正在构建一个使用基于Java Transaction API(JTA)实现的事务管理器的微服务。

我的问题是事务管理器是否有能力处理分布式数据库场景中的并发问题。

场景:

假设有多个服务实例正在运行,我们收到两个请求,要求在帐户中将余额金额更新10。最初一个帐户可以有100美元,第一个实例得到它并将其增加到10美元但尚未提交。

同时第二个实例也是retreive的帐户,它仍然是100并将其增加10美元然后将其更新余额提交到110美元,然后将一个更新帐户再次服务到110美元。

到这个时候你必须想到平衡应该增加$ 20而不是10.我是否必须编写某种乐观锁定异常机制来防止上述情况,或者基于JTA规范的事务管理器是否已经确保这样的事情不会发生 ?

java concurrency microservices distributed-transactions optimistic-locking
3个回答
1
投票

事务管理器是否有能力处理分布式数据库方案中的并发问题。

事务和并发是两个独立的概念,虽然事务在我们也看到并发的上下文中变得最重要,但事务在没有并发的情况下可能很重要。

回答你的问题:不,事务管理器通常不关心处理并发更新引起的问题。它需要一种非常天真和简单(通常是最有意义的)方法:如果在事务开始之后,它检测到状态变得不一致(由于并发更新),它只会将其作为异常引发并回滚事务。如果只有它可以确定事务的ACID属性的所有条件仍然有效,它将提交事务。


0
投票

对于此类请求,您可以通过乐观并发处理,您可以在数据库上使用列(Timestamp)作为对版本号的引用。

每次提交更改时,它都会修改时间戳值。

如果两个请求尝试同时提交更改,则只有其中一个请求将成功,因为版本(时间戳)列将更改,然后否定其他请求进行更改。


0
投票

事务管理器(作为JTA规范的实现)使得透明工作在多个资源之上。它确保所有操作都作为一个单独的工作单元发生。 “在多个资源之上工作”意味着应用程序可以将数据插入数据库,同时它向JMS代理发送消息。事务管理器保证为这两个操作保留ACID属性。以简单的形式,当事务成功完成时,应用程序开发人员可以确保两个操作都已处理完毕。当发生一些麻烦时,事务管理器会处理它 - 可能抛出异常并回滚数据更改。因此,没有处理任何操作。它使应用程序开发人员不需要关心更新第一个数据库然后更新JMS并检查是否所有数据更改都已真正处理或发生故障。

一般而言,JTA规范并未考虑微服务架构。现在它真的取决于你的系统设计(!)但是如果我认为你有两个微服务,每个微服务都附加了自己的事务管理器,那么事务管理器就无法帮助你解决你的并发问题。事务管理器(通常)在某些同步中不起作用。您不能使用来自一个微服务的多个资源(事务管理器的用例是什么),而是使用来自多个微服务的一个资源。

由于存在一个资源,因此它是所有更新的同步点。它取决于它如何管理并发。考虑到它是一个SQL数据库,那么它取决于它使用的隔离级别(ACID - I =隔离,请参阅https://en.wikipedia.org/wiki/ACID_(computer_science))。您的特定示例讨论了丢失的更新现象(https://vladmihalcea.com/a-beginners-guide-to-database-locking-and-the-lost-update-phenomena/)。因为两个微服务都试图更新一条记录。避免此问题的一个解决方案是使用乐观/悲观锁定(您可以通过如上所述的时间戳自行实现),另一种是在数据库中使用可序列化隔离级别,或者您可以将应用程序设计为不读取并根据第一次读取的内容更新数据,但更改具有更新原子的sql查询(或者可能还有其他策略如何使用数据模型来实现所需的结果)。

总之 - 它取决于您的事务管理器的实现方式,它可以在某种程度上帮助您,但它不是它的目的。您的目标应该是检查共享存储中隔离级别的设置方式,并考虑您的应用程序是否需要在应用程序级别处理丢失的更新现象,或者您的存储可以为您管理它。

© www.soinside.com 2019 - 2024. All rights reserved.