前言

由于业务需要,在单体Spring Boot项目中需要引入分布式事务,来保证单体应用连接的多个数据源的事务统一。

而说到分布式事务,小伙伴们肯定会想到阿里的Seata,阿里Seata强大的AT模式确实是解决分布式事务的一剂良药,

但是熟悉Seata的小伙伴肯定知道,使用Seata需要单独搭建Seata服务端来支持分布式事务,而对于一个单体应用项目有必要专门搭建这套服务端吗?

这是一个值得考虑的问题。王子认为技术选型的一个标准就是,用尽可能简单的方式解决复杂的问题。

于是,Atomikos出现了。至于什么是Atomikos这里就不介绍了,网上资料一大堆。本文主要是介绍引入Atomikos后出现的一些问题和解决方案。

引入Atomikos后的第一个坑

好了,下面我们进入正题,看看王子是如何引入Atomikos的。

说明:以下内容不是引入Atomikos的所有工作,王子只是做了个简单介绍,如果需要完整引入还需要参考其他文章。

要使用Atomikos当然要先在Maven中引入它的依赖了,它的依赖如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>

这里我们省略一些必要的配置内容,

在配置数据源的过程中一定会有类似下边这部分的代码,用来配置Atomikos:

        AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
        ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
        ds.setUniqueResourceName(dataSourceName);
        ds.setMinPoolSize(5);
        ds.setMaxPoolSize(20);
        ds.setBorrowConnectionTimeout(60);
        ds.setXaProperties(prop);

第一个坑来了,在配置这部分内容中,王子开始时是没有配置下边这部分内容的。

        ds.setMinPoolSize(5);
        ds.setMaxPoolSize(20);
        ds.setBorrowConnectionTimeout(60);

这个时候,运行程序一切正常,包括它的分布式事务,王子也已经测试通过了。

但是,当运行应用中Quartz定时任务的时候,悲剧发生了,控制台直接报如下异常:

[ERROR][-- ::,][org.hibernate.engine.jdbc.spi.SqlExceptionHelper]Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.
[ERROR][-- ::,][org.apache.struts2.dispatcher.Dispatcher]Exception occurred during processing request: Could not open connection

现在对于这个第一个坑的解决方案相信大家已经清楚了,就是要配置刚才我们提到的那三行内容。

第二个坑

现在我们成功的解决了第一个坑,重启程序再次测试Quartz定时任务,看到应用中那还是一直在转的圈圈(头痛)。

整合Atomikos、Quartz、Postgresql的踩坑日记-LMLPHP

经过对报错日志的分析之后,发现了一行有用的信息,如下:

Caused by: org.postgresql.util.PSQLException: ERROR: prepared transactions are disabled
  Suggerimento: Set max_prepared_transactions to a nonzero value.

看到这里其实就很明显了,翻译过来就是给max_prepared_transactions这个参数设置一个非0的值。

解决方案就是找到Postgresql数据库的postgresql.conf文件,修改这个值即可。

max_prepared_transactions默认是0,我们把它改成与max_connections一样大就可以了。

总结

本文主要是记录一下日常工作中踩到的坑,防止再犯同样的问题。

对于第一个坑,属于Atomikos的配置问题,小伙伴们可以做一个了解。

对于第二个坑,王子这里使用的是Postgresql数据库,所以导致了这个问提,建议如果使用Postgre数据库都开启一下这个参数,防止后患。

最后王子说明一下,Atomikos只适用于类似本文中的这种小规模系统,它的底层是XA的2PC方案,会对数据库资源有一定的锁定过程,所以性能不是很高。

所以,对于要考虑高并发、高性能的系统,分布式事务框架还是要优先选择Seata。

往期文章推荐:

JVM专栏

消息中间件专栏

并发编程专栏

整合Atomikos、Quartz、Postgresql的踩坑日记-LMLPHP

04-27 23:00