我们可以编写自定义的Spring事务管理器吗?

时间:2019-08-20 08:44:17

标签: java spring transactions

假设我们有一个businessLogic()方法可以完成两件事:在本地缓存中写入一些信息,并使用JDBC在DB中保存相同的信息,以便缓存和DB的内容总是一样的。

我知道我们可以使用Spring的JDBC数据源事务管理器在发生异常的情况下自动回滚数据库。但是,在这种情况下,我们如何定义一个自定义事务管理器,该管理器也回滚缓存的内容,以使缓存的内容与数据库始终保持同步?

谢谢。

3 个答案:

答案 0 :(得分:1)

Gab的答案是正确的,除了不正确的部分。

XA确实是协调多种资源更新的标准方法...除了缓存是本地的(即进程内)外,它不一定是资源。

缓存并不完全是“实现JTA”,它根据XA协议的部署方式充当XA协议中的两个角色之一。它可以是XAResource,但是通常仅在其生命周期不同于客户端进程的生命周期时才需要。对于进程内使用,它更有可能是同步。

这些角色之间的主要区别是:XAResource是容错的,但是同步不是。对于客户端进程内存中的易失性缓存,在崩溃后通过查询数据库来重建缓存就足够了。对于无法使用的缓存,在db tx提交之后但在缓存更新之前,客户端崩溃会使缓存不同步,至少直到缓存过期或被手动刷新为止。

根据缓存的实现,不能保证它将自动选择正确的模式。请参阅配置参考以了解您选择的实现方式,例如https://infinispan.org/docs/stable/user_guide/user_guide.html#tx_sync_enlist

Spring实际上也不是JTA XA事务管理器,尽管它确实在它们之上提供了一个抽象层。可以使用Spring在非XA模式下驱动数据库,但是这样就不需要标准的挂钩来实现缓存同步,而需要专有接口。或者,您可以让数据库通过一阶段资源适配器执行伪XA。完整的2PC可能对您的用例来说是过大的。

答案 1 :(得分:0)

首先,我认为缓存的事务管理任务是多余的。我建议您仅在成功提交数据库级事务后才更新缓存。

如果在数据库中的实体更新与其缓存状态之间存在很小的窗口,则大多数使用缓存的方案都是可以接受的。

如果您的案例拒绝了缓存过时的任何可能性,那么您可能必须避免使用缓存或使用一些特殊的缓存(可能与支持事务的原始数据相同的数据库)。否则,您在尝试维护两个不同系统(数据库级和缓存级)之间的一致性时遇到问题。在大多数情况下,您可以实现的最好结果就是最终的一致性-这意味着无论如何您将拥有状态不一致的窗口,只有这样(最终),数据才会变得一致。

答案 2 :(得分:0)

处理分布在多个资源中的事务的标准方法是使用XA

然后,您必须使用xa数据源访问数据库,并使用实现JTA的缓存实现,例如。 ehcache

我对Spring Boot不太熟悉,但是事务管理器应该使用适当的配置(无需重写任何内容)立即管理两种资源之间的事务同步。