项目中使用sharding-jdbc导致启动慢的解决办法

环境:springboot2.3.9.RELEASE + shardingsphere4.0.1 + Oracle


当连接oracle数据库的当前用户下表少的时候可能感觉不出来,当数据表很多时会导致服务启动超级慢,我项目中有200多张表,启动服务时非常的慢。

  • 定位问题

通过debug调试,定位到
TableMetaDataInitializer.java这个类中的如下方法在启动服务时非常的耗时。

private Map<String, TableMetaData> loadDefaultTables(final ShardingRule shardingRule) throws SQLException {
        Map<String, TableMetaData> result = new HashMap<>(shardingRule.getTableRules().size(), 1);
        Optional<String> actualDefaultDataSourceName = shardingRule.findActualDefaultDataSourceName();
        if (actualDefaultDataSourceName.isPresent()) {
            for (String each : getAllTableNames(actualDefaultDataSourceName.get())) {
                result.put(each, tableMetaDataLoader.load(each, shardingRule));
            }
        }
        return result;
    }

这里的getAllTableNames方法是获取当前用户下的所有的表,然后一个一个地遍历去加载表的元信息。

tableMetaDataLoader.load(each, shardingRule); 这个方法就是用来加载表的元信息的。

  • 解决办法

方案1:

不让其加载表的元信息,也就是将如下代码注释了:

/*for (String each : getAllTableNames(actualDefaultDataSourceName.get())) {
         result.put(each, tableMetaDataLoader.load(each, shardingRule));
 }*/

我项目中是将这个代码注释了后,启动恢复了正常,同时使用的分表功能也是正常的;但是这样总感觉是有风险的(具体也没研究注释的那代码用处是什么)。至少在我们项目中将这代码注释了后确实也没有影响到系统分表的功能,一切正常。

方案2:

通过多线程的方式解决问题,在循环加载那,通过多线程来提高加载速度。

private static ThreadPoolExecutor executors = new ThreadPoolExecutor(20, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10000)) ;
private static Logger logger = LoggerFactory.getLogger(TableMetaDataInitializer.class) ;

private Map<String, TableMetaData> loadDefaultTables(final ShardingRule shardingRule) throws Exception {
        Map<String, TableMetaData> result = new ConcurrentHashMap<>(shardingRule.getTableRules().size(), 1);
        Optional<String> actualDefaultDataSourceName = shardingRule.findActualDefaultDataSourceName();
        if (actualDefaultDataSourceName.isPresent()) {
        	Collection<String> tables = getAllTableNames(actualDefaultDataSourceName.get()) ;
        	CountDownLatch cdl = new CountDownLatch(tables.size()) ;
        	logger.info("加载 {} 张表", tables.size());
            for (String each : tables) {
            	executors.execute(() -> {
            		try {
						result.put(each, tableMetaDataLoader.load(each, shardingRule));
						logger.info("表  {} 元信息加载完成", each) ;
						cdl.countDown() ; 
					} catch (SQLException e) {
						cdl.countDown() ;
						logger.error("加载 {} 元信息错误:{}", each, e) ;
					}
            	}); 
            }
            cdl.await() ;
            executors.shutdown() ;
        }
        return result;
    }

这里通过线程池的方式来提高加载速度,同时为了是系统正常运行正常,这里通过CountDownLatch来保证所有的表元信息都加载完了后程序再继续运行。避免出现看着服务是启动完了,实际加载表信息还在执行中问题。


如果你使用的是这个版本shardingsphere4.1.1,那么可就没有这个类了(服务启动正常了),但是启动服务可能报如下错误:

项目中使用sharding-jdbc导致启动慢的解决办法

 

在我项目中出现上面错误时,做如下处理:

修改
org.apache.shardingsphere.sql.parser.binder.metadata.util.JdbcUtil.java这个类:

源代码:

public static String getSchema(final Connection connection, final String databaseType) {
        String result = null;
        try {
            if ("Oracle".equals(databaseType)) {
                return null;
            }
            result = connection.getSchema();
        } catch (final SQLException ignore) {
        }
        return result;
    }

这里会将当前用户能访问到的所有表进行加载,修改如下只加载当前用户下的,不管其他用户表

public static String getSchema(final Connection connection, final String databaseType) {
        String result = null;
        try {
            result = connection.getSchema();
        } catch (final SQLException ignore) {
        }
        return result;
    }

如上修改完后,启动服务控制台输出如下:

项目中使用sharding-jdbc导致启动慢的解决办法

 

非常的快了。

但是在我们项目中最终没有用这个版本,因为在我们的项目中使用这个版本后查询的数据全都是null,条数是对的,数据都是null,不知道为何!!!

项目中使用sharding-jdbc导致启动慢的解决办法

 

项目中使用sharding-jdbc导致启动慢的解决办法

 

项目中使用sharding-jdbc导致启动慢的解决办法

 

项目中使用sharding-jdbc导致启动慢的解决办法

 

项目中使用sharding-jdbc导致启动慢的解决办法

 

项目中使用sharding-jdbc导致启动慢的解决办法

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
您好!使用Sharding-JDBCSpring Boot项目进行数据库分片是一个不错的选择。下面是一些步骤来集成Sharding-JDBCSpring Boot项目: 第一步,添加Sharding-JDBC依赖到项目的pom.xml文件: ```xml <dependency> <groupId>io.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> </dependency> ``` 第二步,配置Sharding-JDBC相关的数据源和规则。可以在application.properties或application.yml文件进行配置,例如: ```yaml spring: shardingsphere: datasource: names: ds0, ds1 ds0: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/db0 username: root password: password ds1: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/db1 username: root password: password sharding: tables: user: actual-data-nodes: ds${0..1}.user_${0..1} table-strategy: inline: sharding-column: id algorithm-expression: user_${id % 2} ``` 在上面的示例,配置了两个数据源(ds0和ds1),并指定了分片规则:根据user表的id字段进行分片,将数据分散到ds0.user_0、ds0.user_1、ds1.user_0、ds1.user_1这四个表。 第三步,使用Sharding-JDBC的数据源进行数据库操作。在需要使用数据库的地方,注入ShardingDataSource数据源,例如: ```java @Autowired private DataSource dataSource; public void queryData() { try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement()) { ResultSet resultSet = statement.executeQuery("SELECT * FROM user"); while (resultSet.next()) { // 处理查询结果 } } catch (SQLException e) { // 异常处理 } } ``` 以上是使用Sharding-JDBCSpring Boot项目进行数据库分片的基本步骤,您可以根据具体需求进行更详细的配置和使用。希望能对您有所帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值