动态数据源多种实现方式及对比详细介绍

文章目录

      • 动态数据源实现方式
        • 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)能够提供高性能支持。
  • 特殊需求:对于少数特殊业务场景,手动切换数据源可能是最灵活的方案,但维护成本较高。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/429422.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LLM - 理解 多模态大语言模型(MLLM) 的 对齐微调(Alignment) 与相关技术 (五)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142354652 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 完备(F…

为什么git有些commit记录,只有git reflog可以看到,git log看不到?

文章目录 原因分析1. git log 只能显示 **可达的** 提交2. git reflog 记录所有引用的变更 常见导致 git log 看不到提交的原因1. git reset 操作2. git rebase 操作3. 分支删除4. git commit --amend5. 垃圾回收&#xff08;GC&#xff09;* 如何恢复 git log 看不到的提交&am…

带你0到1之QT编程:十七、Http协议实战,实现一个简单服务器和一个客户端进行http协议通信

此为QT编程的第十七谈&#xff01;关注我&#xff0c;带你快速学习QT编程的学习路线&#xff01; 每一篇的技术点都是很很重要&#xff01;很重要&#xff01;很重要&#xff01;但不冗余&#xff01; 我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点&#xff01; …

DEPLOT: One-shot visual language reasoning by plot-to-table translation论文阅读

文章链接&#xff1a;https://arxiv.org/abs/2308.01979http://arxiv.org/abs/2212.10505https://arxiv.org/abs/2308.01979 源码链接&#xff1a;https://github.com/cse-ai-lab/RealCQA 启发&#xff1a;two-stage方法可能是未来主要研究方向&#xff0c;能够增强模型可解释…

利用AI增强现实开发:基于CoreML的深度学习图像场景识别实战教程

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

网络安全-利用 Apache Mod CGI

目录 一、环境 二、开始操作 三、总结 一、环境 蚁剑官网拉取 二、开始操作 蚁剑连接 一样终端命令不能执行 可以看到putenv已经禁用 我们开始一下&#xff0c;跳入一个新终端且可以执行命令 我们具体看一下干了什么事情 上传了一个htaccess这个文件的作用是让以后所有ant文…

LAMP架构搭建

目录 LAMP架构搭建 编译安装Apache httpd服务 1、需要的安装包 2、关闭防火墙和核心防护 3、安装环境依赖包 4、配置软件模块 5、编译及安装 6、优化配置文件路径&#xff08;可不做&#xff09; 7、添加httpd系统服务 8、修改httpd 服务配置文件 9、浏览器访问验证…

【Pycharm】Pycharm创建Django提示pip版本需要升级

目录 1、现象 2、分析 3、本质 前言&#xff1a;经常使用pycharm创建django、flask等项目时候提示pip版本需要升级&#xff0c;解决方案 1、现象 使用Pycharm创建Django项目提示安装Django超时&#xff0c;报错建议pip升级22升级到24 2、分析 之前使用命令升级了pip到了24…

linux 基础(一)mkdir、ls、vi、ifconfig

1、linux简介 linux是一个操作系统&#xff08;os: operating system&#xff09; 中国有没有自己的操作系统&#xff08;华为鸿蒙HarmonyOS&#xff0c;阿里龙蜥(Anolis) OS 8、百度DuerOS都有&#xff09; 计算机组的组成&#xff1a;硬件软件 硬件&#xff1a;运算器&am…

思通数科开源产品:免费的AI视频监控卫士安装指南

准备运行环境&#xff1a; 确保您的服务器或计算机安装了Ubuntu 18.04 LTS操作系统。 按照产品要求&#xff0c;安装以下软件&#xff1a; - Python 3.9 - Java JDK 1.8 - MySQL 5.5 - Redis 2.7 - Elasticsearch 8.14 - FFmpeg 4.1.1 - RabbitMQ 3.13.2 - Minio &#xff08;…

240912-设置WSL中的Ollama可在局域网访问

A. 最终效果 B. 设置Ollama&#xff08;前提&#xff09; sudo vim /etc/systemd/system/ollama.service[Unit] DescriptionOllama Service Afternetwork-online.target[Service] ExecStart/usr/bin/ollama serve Userollama Groupollama Restartalways RestartSec3 Environme…

​OpenAI最强模型o1系列:开启人工智能推理新时代

前不久OpenAI发布全新模型——o1模型&#xff0c;也就是业界说的“草莓模型”&#xff0c;包含三款型号&#xff1a;OpenAI o1、OpenAI o1-preview和OpenAI o1-mini。 其中&#xff0c;OpenAI o1-mini和 o1-preview已经对用户开放使用&#xff1a; OpenAI o1&#xff1a;高级推…

C语言之预处理详解(完结撒花)

目录 前言 一、预定义符号 二、#define 定义常量 三、#define定义宏 四、宏与函数的对比 五、#和## 运算符 六、命名约定 七、#undef 八、条件编译 九、头文件的包含 总结 前言 本文为我的C语言系列的最后一篇文章&#xff0c;主要讲述了#define定义和宏、#和##运算符、各种条件…

植物大战僵尸【源代码分享+核心思路讲解】

植物大战僵尸已经正式完结&#xff0c;今天和大家分享一下&#xff0c;话不多说&#xff0c;直接上链接&#xff01;&#xff01;&#xff01;&#xff08;如果大家在运行这个游戏遇到了问题或者bug&#xff0c;那么请私我谢谢&#xff09; 大家写的时候可以参考一下我的代码思…

前端工程化4:从0到1构建完整的前端监控平台

前言 一套完整的前端监控系统的主要部分&#xff1a; 数据上报方式数据上送时机性能数据采集错误数据采集用户行为采集定制化指标监控sdk 监控的目的&#xff1a; 一、数据上报方式 本文的方案是&#xff0c;优先navigator.sendBeacon&#xff0c;降级使用1x1像素gif图片…

群晖NAS使用Docker本地部署网页版Ubuntu系统并实现无公网IP远程访问

文章目录 前言1. 下载Docker-Webtop镜像2. 运行Docker-Webtop镜像3. 本地访问网页版Linux系统4. 群晖NAS安装Cpolar工具5. 配置异地访问Linux系统6. 异地远程访问Linux系统7. 固定异地访问的公网地址 前言 本文旨在详细介绍如何在群晖NAS部署docker-webtop&#xff0c;并结合c…

《财富之眼:用经济思维看清世界》pdf电子书下载

《财富之眼&#xff1a;用经济思维看清世界》pdf电子书下载 内容简介 一切社会现象都是经济现象&#xff0c;我们只能赚到自己认知范围内的 钱。我国社会主要矛盾已经转化为人民日益增长的美好生活需要和不 平衡不充分的发展之间的矛盾&#xff0c;其中“不平衡不充分”很大程…

【网络】高级IO——Reactor版TCP服务器

目录 1.什么是Reactor 1.1.餐厅里的Reactor模式 2.Reactor的由来 2.1.单 Reactor 单进程 / 线程 2.2.单 Reactor 多线程 / 多进程 2.3.多 Reactor 多进程 / 线程 3.实现单 Reactor 单进程版本的TCP服务器 3.1.Connection类 3.2.TcpServer类 3.3.Connection的真正用处 …

C++—vector的常见接口与用法(正式进入STL)

目录 0.提醒 1.介绍 2.构造 1.正常构造 2.默认值构造 3.调用默认构造函数构造 3.遍历 1.迭代器 2.范围for 3.下标访问 4.容量 1.capacity&#xff1a;返回当前容器的容量 2.reserve&#xff1a;如果传的k比当前容量大&#xff0c;则扩容到比k大或者等于k的数&…

Windows10安装cuda11.3.0+cudnn8.5.0,以及创建conda虚拟环境(pytorch)

1、检查电脑驱动版本为561.09&#xff0c;选择cuda版本&#xff0c;下图可知cuda版本<12.6。 nvidia-smi #查看驱动版本&#xff0c;以及最大可以安装的cuda版本 2、Anaconda3-2024.06-1-Windows-x86_64.exe下载&#xff1a; 官网&#xff1a;https://www.baidu.com/link?…