您的位置:首页 > 财经 > 产业 > 最新新闻热点及观点_游戏打金工作室加盟_如何推广_如何联系百度人工客服电话

最新新闻热点及观点_游戏打金工作室加盟_如何推广_如何联系百度人工客服电话

2024/11/18 12:18:13 来源:https://blog.csdn.net/qq_42631788/article/details/142420958  浏览:    关键词:最新新闻热点及观点_游戏打金工作室加盟_如何推广_如何联系百度人工客服电话
最新新闻热点及观点_游戏打金工作室加盟_如何推广_如何联系百度人工客服电话

文章目录

      • 动态数据源实现方式
        • 1. 概述
        • 2. 动态数据源实现方式
          • 2.1 基于 `AbstractRoutingDataSource` 实现动态数据源
          • 2.2 基于 Spring AOP 实现动态数据源
          • 2.3 基于 `TransactionManager` 实现动态数据源
          • 2.4 通过数据库中间件实现动态数据源(ShardingSphere、MyCAT)
        • 3. 各实现方式对比
        • 4. 总结

动态数据源实现方式


1. 概述

动态数据源是现代企业级应用中常见的需求,尤其是在 多数据源管理读写分离多租户系统分库分表 等场景中,动态切换不同的数据源可以提升系统的灵活性和性能。本文将详细介绍几种常见的动态数据源实现方式,包括其应用场景、实现步骤、优缺点对比。


2. 动态数据源实现方式
2.1 基于 AbstractRoutingDataSource 实现动态数据源

适用场景
主要适用于需要根据业务上下文动态切换数据源的场景,常用于 读写分离多租户系统 等应用。

实现原理
Spring 框架提供的 AbstractRoutingDataSource 类支持动态数据源路由。通过继承该类并重写 determineCurrentLookupKey() 方法,基于当前线程上下文中的数据源标识符进行数据源切换。

实现步骤

  1. 创建数据源配置类:定义多个数据源,并将它们注入 DynamicDataSource
@Configuration
public class DataSourceConfig {@Bean(name = "dataSource1")@ConfigurationProperties(prefix = "spring.datasource.db1")public DataSource dataSource1() {return DataSourceBuilder.create().build();}@Bean(name = "dataSource2")@ConfigurationProperties(prefix = "spring.datasource.db2")public DataSource dataSource2() {return DataSourceBuilder.create().build();}@Primary@Bean(name = "dynamicDataSource")public DataSource dynamicDataSource(@Qualifier("dataSource1") DataSource dataSource1,@Qualifier("dataSource2") DataSource dataSource2) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put("db1", dataSource1);targetDataSources.put("db2", dataSource2);DynamicDataSource dynamicDataSource = new DynamicDataSource();dynamicDataSource.setTargetDataSources(targetDataSources);dynamicDataSource.setDefaultTargetDataSource(dataSource1);return dynamicDataSource;}
}
  1. 创建 DynamicDataSourceContextHolder:使用 ThreadLocal 管理数据源标识。
public class DynamicDataSourceContextHolder {private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();public static void setDataSourceType(String dataSourceType) {CONTEXT_HOLDER.set(dataSourceType);}public static String getDataSourceType() {return CONTEXT_HOLDER.get();}public static void clearDataSourceType() {CONTEXT_HOLDER.remove();}
}
  1. 创建 DynamicDataSource:继承 AbstractRoutingDataSource 并重写 determineCurrentLookupKey() 方法。
public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceContextHolder.getDataSourceType();}
}
  1. 使用 AOP 切面动态切换数据源
@Aspect
@Component
public class DynamicDataSourceAspect {@Before("@annotation(ds)")public void switchDataSource(JoinPoint point, DataSource ds) {DynamicDataSourceContextHolder.setDataSourceType(ds.value());}@After("@annotation(ds)")public void clearDataSource(JoinPoint point, DataSource ds) {DynamicDataSourceContextHolder.clearDataSourceType();}
}
  1. 使用自定义注解 @DataSource 指定数据源:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {String value() default "db1";
}

优点

  • 实现简单,轻松与 Spring 框架集成。
  • 适用于小型项目的动态数据源需求。

缺点

  • 性能可能在复杂场景中遇到瓶颈。

2.2 基于 Spring AOP 实现动态数据源

适用场景
适合需要细粒度动态切换数据源的场景,比如特定方法或业务逻辑需要在不同的数据源中执行。

实现原理
通过 Spring AOP 技术,在方法执行前后拦截调用,根据自定义注解切换数据源。

实现步骤

  1. 创建自定义注解 @DataSource
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {String value();
}
  1. 定义 AOP 切面类
@Aspect
@Component
public class DynamicDataSourceAspect {@Before("@annotation(ds)")public void switchDataSource(JoinPoint point, DataSource ds) {DynamicDataSourceContextHolder.setDataSourceType(ds.value());}@After("@annotation(ds)")public void clearDataSource(JoinPoint point, DataSource ds) {DynamicDataSourceContextHolder.clearDataSourceType();}
}
  1. 在业务层使用 @DataSource 注解 切换数据源:
@Service
public class UserService {@DataSource("db1")public List<User> getAllUsersFromDb1() {// 从 db1 获取数据}@DataSource("db2")public List<User> getAllUsersFromDb2() {// 从 db2 获取数据}
}

优点

  • 实现灵活,支持细粒度的控制。
  • 易于使用,适合小范围数据源切换。

缺点

  • 随着项目的规模增加,过多的切面可能导致维护复杂性上升。

2.3 基于 TransactionManager 实现动态数据源

适用场景
用于需要在不同数据源之间切换并保持事务一致性的场景,特别适合有 多数据源事务管理 需求的应用。

实现原理
通过为每个数据源配置不同的 TransactionManager,在 @Transactional 注解中动态指定事务管理器,确保数据源切换时的事务一致性。

实现步骤

  1. 配置每个数据源的 TransactionManager
@Bean
public PlatformTransactionManager transactionManager1(@Qualifier("dataSource1") DataSource dataSource1) {return new DataSourceTransactionManager(dataSource1);
}@Bean
public PlatformTransactionManager transactionManager2(@Qualifier("dataSource2") DataSource dataSource2) {return new DataSourceTransactionManager(dataSource2);
}
  1. 使用 @Transactional 注解指定事务管理器
@Service
public class UserService {@Transactional("transactionManager1")public void performDb1Operation() {// 操作 db1}@Transactional("transactionManager2")public void performDb2Operation() {// 操作 db2}
}

优点

  • 支持多数据源的事务管理,保证数据一致性。
  • 适合需要事务支持的场景。

缺点

  • 配置复杂,特别是涉及到分布式事务时。

2.4 通过数据库中间件实现动态数据源(ShardingSphere、MyCAT)

适用场景
适用于 大规模分库分表读写分离 等复杂场景,尤其是对性能有较高要求的项目。

实现原理
使用数据库中间件(如 ShardingSphere、MyCAT),通过中间件实现数据源路由、分片、读写分离等功能。开发者不需要手动处理数据源切换,所有逻辑由中间件根据配置文件自动完成。

实现步骤

  1. 引入 ShardingSphere 依赖
<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-core</artifactId><version>x.x.x</version>
</dependency>
  1. 配置数据源和路由规则

application.yml 中配置数据源和分片规则。

sharding:data-sources:ds_0:url: jdbc:mysql://localhost:3306/db0username: rootpassword: rootds_1:url: jdbc:mysql://localhost:3306/db1username: rootpassword: root

优点

  • 中间件提供高性能支持,适合复杂的大规模场景。
  • 减少了开发者手动管理多数据源的工作量。

缺点

  • 学习成本较高,配置复杂。
  • 对中间件的稳定性有较高的依赖。


3. 各实现方式对比
实现方式适用场景优点缺点
AbstractRoutingDataSource读写分离、多租户简单易用,与 Spring 框架无缝集成在复杂场景中可能存在性能瓶颈
基于 Spring AOP细粒度数据源切换灵活,支持特定方法和类的动态切换过多切面可能增加调试和维护难度
基于 TransactionManager多数据源事务管理保证多数据源场景中的事务一致性配置复杂,特别是分布式事务时
数据库中间件(ShardingSphere等)分库分表、读写分离性能优异,适合复杂场景,开发者不需手动处理学习成本高,依赖中间件性能和稳定性
手动切换数据源特殊业务场景完全控制数据源切换,灵活实现复杂,维护成本高

4. 总结

动态数据源技术为企业级应用提供了灵活的数据库管理能力。不同的实现方式各有优劣,开发者需要根据项目规模、业务需求和性能要求进行选择。

  • 小型项目:可以选择基于 AbstractRoutingDataSource 或 Spring AOP 的实现,简单易用,能够快速满足动态切换需求。
  • 需要事务管理:对于涉及多数据源事务管理的项目,基于 TransactionManager 的方式更为适合,可以保证数据一致性。
  • 大规模项目:如果是分库分表或读写分离场景,数据库中间件(如 ShardingSphere)能够提供高性能支持。
  • 特殊需求:对于少数特殊业务场景,手动切换数据源可能是最灵活的方案,但维护成本较高。

通过合理的动态数据源选择与实现,能够显著提升系统的扩展性和性能,满足不同复杂业务场景的需求。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com