How to design global distributed transaction(none database)? Can JTA use for none db transaction?

怎甘沉沦 提交于 2019-11-28 18:23:47

You're right, you need two-phase commit support thanks to a XA transaction manager provided by the JTA API.

As far as I know Spring does not provide a transaction manager implementation itself. The JtaTransactionManager only delegates to existing implementation usually provided from JavaEE implementations.

So you will have to plugin a JTA implementation into Spring to get effective job done. Here are some proposals:

Then you will have to implement your resource manager to support two-phase commit. In the JavaEE worlds, it consists in a resource adapter packaged as a RAR archive. Depending on the type of resource, the following aspects are to read/implement:

As examples, I recommend you to look at implementations for the classical "transactions with files" issue:

If you want to write your own transactional resource, you indeed need to implement an XAResource and let it join an ongoing transaction, handle prepare and commit requests from the transaction manager etc.

Datasources are the most well known transactional resources, but as mentioned they are not the only ones. You already mentioned JMS providers. A variety of Caching solutions (e.g. Infinispan) are also transactional resources.

Implementing XAResources and working with the lower level part of the JTA API and the even lower level JTS (Java Transaction Service) is not a task for the faint of heart. The API can be archaic and the entire process is only scarcely documented.

The reason is that regular enterprise applications creating their own transactional resources is extremely rare. The entire point of being transactional is to do an action that is atomic for an external observer.

To be observable in the overwhelming majority of cases means the effects of the action are present in a database. Nearly each and every datasource is already transactional, so that use case is fully covered.

Another observable effect is whether a message has been send or not, and that too is fully covered by the existing messaging solutions.

Finally, updating a (cluster-wide) in memory map is yet another observable effect, which too is covered by the major cache providers.

There's a remnant of demand for transactional effects when operating with external enterprise information systems (EIS), and as a rule of thumb the vendors of such systems provide transaction aware connectors.

The shiver of use cases that remain is so small that apparently nobody ever really bothered to write much about it. There are some blogs out there that cover some of the basics, but much will be left to your own experimentation.

Do try to verify for yourself if you really absolutely need to go down this road, and if your need can't be met by one of the existing transactional resources.

You could do the following (similar to your checkpoint strategy):

  1. TaskA executes in a (local) JTA transaction and tries to reserve the necessary resources before it delegates to your subtasks

  2. Subtask invocations are done via JMS/XA: if step 1 fails, no subtask will ever be triggered and if step 1 commits then the JMS invocations will be received at each subtask

  3. Subtasks (re)try to process their invocation message with a JMS max redelivery limit set (see your JMS vendor docs on how to do this)

  4. Configure a "dead letter queue" for any failures in 3.

This works, assuming that:

-retrying in step 3 makes sense

-there is a bit of human intervention needed for messages in the dead letter queue

If this is not acceptable then there is also TCC: http://www.atomikos.com/Main/DownloadWhitepapers?article=TccForRestApi.pdf - this can be seen as a "reservation" pattern for REST services.

Hope this helps

Guy

http://www.atomikos.com

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!