前言
由于业务需要,在单体Spring Boot项目中需要引入分布式事务,来保证单体应用连接的多个数据源的事务统一。
而说到分布式事务,小伙伴们肯定会想到阿里的Seata,阿里Seata强大的AT模式确实是解决分布式事务的一剂良药,
但是熟悉Seata的小伙伴肯定知道,使用Seata需要单独搭建Seata服务端来支持分布式事务,而对于一个单体应用项目有必要专门搭建这套服务端吗?
这是一个值得考虑的问题。王子认为技术选型的一个标准就是,用尽可能简单的方式解决复杂的问题。
于是,Atomikos出现了。至于什么是Atomikos这里就不介绍了,网上资料一大堆。本文主要是介绍引入Atomikos后出现的一些问题和解决方案。
引入Atomikos后的第一个坑
好了,下面我们进入正题,看看王子是如何引入Atomikos的。
说明:以下内容不是引入Atomikos的所有工作,王子只是做了个简单介绍,如果需要完整引入还需要参考其他文章。
要使用Atomikos当然要先在Maven中引入它的依赖了,它的依赖如下:
代码语言:javascript复制 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
这里我们省略一些必要的配置内容,
在配置数据源的过程中一定会有类似下边这部分的代码,用来配置Atomikos:
代码语言:javascript复制 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);
第一个坑来了,在配置这部分内容中,王子开始时是没有配置下边这部分内容的。
代码语言:javascript复制 ds.setMinPoolSize(5);
ds.setMaxPoolSize(20);
ds.setBorrowConnectionTimeout(60);
这个时候,运行程序一切正常,包括它的分布式事务,王子也已经测试通过了。
但是,当运行应用中Quartz定时任务的时候,悲剧发生了,控制台直接报如下异常:
代码语言:javascript复制[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定时任务,看到应用中那还是一直在转的圈圈(头痛)。
经过对报错日志的分析之后,发现了一行有用的信息,如下:
代码语言:javascript复制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。