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

时间:2018-08-07 18:46:11

标签: java concurrency microservices distributed-transactions optimistic-locking

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

我的问题是Trasaction maanger是否有能力处理分布式数据库方案中的并发问题。

场景:

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

与此同时,第二个实例还撤回了仍为100的帐户,并将其增加了$ 10,然后将其更新为$ 110,然后又为一个更新帐户提供了$ 110。

这一次您必须已经确定应该将余额增加$ 20而不是$ 10。是否必须编写某种Optimistic锁异常机制来防止上述情况发生?或者基于JTA规范的Transaction Manager是否已确保这样的事情不会发生吗?

3 个答案:

答案 0 :(得分:1)

  

Trasaction maanger是否有能力处理分布式数据库方案中的并发问题。

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

要回答您的问题:否,事务管理器通常不会处理并发更新引起的问题。它采用一种非常幼稚且简单的方法(通常是最有意义的方法):如果在事务开始之后检测到状态变得不一致(由于并发更新),它将简单地将其引发为异常并回滚事务。如果只能确定事务的ACID属性的所有条件仍然有效,那么它将提交事务。

答案 1 :(得分:0)

对于这种类型的请求,您可以通过Optimistic Concurrency进行处理,在该数据库中,数据库(Timestamp)上会有一列作为对版本号的引用。

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

如果两个请求尝试同时提交更改,则只有一个成功,因为版本(Timestamp)列将更改,然后否决其他请求以提交更改,则该列将更改。

答案 2 :(得分: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查询(或者可能还有其他策略如何与您的数据模型一起使用以实现所需的结果)。

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