|
|
@@ -0,0 +1,197 @@
|
|
|
+# Growth Manager 多数据源配置说明
|
|
|
+
|
|
|
+## 概述
|
|
|
+
|
|
|
+本项目已集成阿里云 AnalyticDB (ADB) 并实现多数据源数据库访问功能。支持在同一个应用中同时访问 MySQL 主数据源和 ADB 数据源。
|
|
|
+
|
|
|
+## 功能特性
|
|
|
+
|
|
|
+- ✅ 支持多数据源动态切换
|
|
|
+- ✅ 基于注解的声明式数据源切换
|
|
|
+- ✅ 支持手动编程式数据源切换
|
|
|
+- ✅ 线程安全的数据源上下文管理
|
|
|
+- ✅ 完整的 Spring 事务支持
|
|
|
+
|
|
|
+## 配置说明
|
|
|
+
|
|
|
+### 1. 数据源配置
|
|
|
+
|
|
|
+在 `application.properties` 和相关环境配置文件中,需要配置两个数据源:
|
|
|
+
|
|
|
+#### 主数据源(MySQL)
|
|
|
+```properties
|
|
|
+# 主数据源配置
|
|
|
+spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver
|
|
|
+spring.datasource.primary.url=jdbc:mysql://your-mysql-host:3306/your_database
|
|
|
+spring.datasource.primary.username=your_username
|
|
|
+spring.datasource.primary.password=your_password
|
|
|
+spring.datasource.primary.initialSize=5
|
|
|
+spring.datasource.primary.maxActive=20
|
|
|
+```
|
|
|
+
|
|
|
+#### ADB 数据源
|
|
|
+```properties
|
|
|
+# ADB 数据源配置
|
|
|
+spring.datasource.adb.driver-class-name=com.mysql.cj.jdbc.Driver
|
|
|
+spring.datasource.adb.url=jdbc:mysql://your-adb-instance-address:3306/your_database?useSSL=true&serverTimezone=Asia/Shanghai
|
|
|
+spring.datasource.adb.username=your_adb_username
|
|
|
+spring.datasource.adb.password=your_adb_password
|
|
|
+spring.datasource.adb.initialSize=5
|
|
|
+spring.datasource.adb.maxActive=20
|
|
|
+```
|
|
|
+
|
|
|
+### 2. ADB 连接信息获取
|
|
|
+
|
|
|
+1. 登录阿里云控制台
|
|
|
+2. 进入 AnalyticDB 控制台
|
|
|
+3. 选择对应的 ADB 实例
|
|
|
+4. 在实例详情中获取:
|
|
|
+ - 连接地址(VPC 地址或公网地址)
|
|
|
+ - 端口(通常为 3306)
|
|
|
+ - 数据库名称
|
|
|
+ - 用户名和密码
|
|
|
+5. 确保应用服务器 IP 已添加到 ADB 白名单
|
|
|
+
|
|
|
+## 使用方式
|
|
|
+
|
|
|
+### 方式一:使用 @DataSource 注解(推荐)
|
|
|
+
|
|
|
+在 Service 方法或类上使用 `@DataSource` 注解指定数据源:
|
|
|
+
|
|
|
+```java
|
|
|
+@Service
|
|
|
+public class YourService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private YourMapper yourMapper;
|
|
|
+
|
|
|
+ // 方法级别注解
|
|
|
+ @DataSource("adb")
|
|
|
+ public List<YourEntity> queryFromAdb() {
|
|
|
+ return yourMapper.selectAll();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 默认使用主数据源
|
|
|
+ public List<YourEntity> queryFromPrimary() {
|
|
|
+ return yourMapper.selectAll();
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 方式二:类级别注解
|
|
|
+
|
|
|
+在整个类上使用 `@DataSource` 注解,该类所有方法都使用指定数据源:
|
|
|
+
|
|
|
+```java
|
|
|
+@Service
|
|
|
+@DataSource("adb")
|
|
|
+public class AdbService {
|
|
|
+ // 所有方法都使用 ADB 数据源
|
|
|
+ public List<YourEntity> query() {
|
|
|
+ return yourMapper.selectAll();
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 方式三:手动切换数据源
|
|
|
+
|
|
|
+在需要动态切换数据源的场景下,可以手动设置:
|
|
|
+
|
|
|
+```java
|
|
|
+@Service
|
|
|
+public class YourService {
|
|
|
+
|
|
|
+ public void queryWithManualSwitch() {
|
|
|
+ try {
|
|
|
+ // 切换到 ADB 数据源
|
|
|
+ DynamicDataSourceContextHolder.setDataSource("adb");
|
|
|
+ // 执行数据库操作
|
|
|
+ List<YourEntity> result = yourMapper.selectAll();
|
|
|
+ return result;
|
|
|
+ } finally {
|
|
|
+ // 务必清除数据源标识
|
|
|
+ DynamicDataSourceContextHolder.clearDataSource();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 数据源标识
|
|
|
+
|
|
|
+系统预定义了以下数据源标识:
|
|
|
+
|
|
|
+- `primary` - 主数据源(MySQL),默认数据源
|
|
|
+- `adb` - ADB 数据源
|
|
|
+
|
|
|
+## 示例代码
|
|
|
+
|
|
|
+项目已包含完整的示例代码,位于:
|
|
|
+
|
|
|
+- `AdbExampleMapper` - ADB Mapper 示例
|
|
|
+- `AdbExampleService` - ADB Service 使用示例
|
|
|
+- `AdbExampleController` - ADB Controller 测试接口
|
|
|
+
|
|
|
+### 测试接口
|
|
|
+
|
|
|
+启动应用后,可以通过以下接口测试多数据源功能:
|
|
|
+
|
|
|
+```
|
|
|
+GET /adb/example/query?tableName=test_table&limit=10
|
|
|
+GET /adb/example/count?tableName=test_table
|
|
|
+```
|
|
|
+
|
|
|
+## 注意事项
|
|
|
+
|
|
|
+1. **数据源切换是线程安全的**:使用 ThreadLocal 实现,每个线程独立的数据源上下文
|
|
|
+2. **务必在 finally 中清除数据源**:手动切换数据源时,必须在 finally 块中调用 `clearDataSource()`
|
|
|
+3. **事务管理**:多数据源场景下,每个数据源有独立的事务管理器
|
|
|
+4. **ADB 连接配置**:ADB 通常需要 SSL 连接,URL 中建议添加 `useSSL=true`
|
|
|
+5. **驱动兼容性**:ADB for MySQL 兼容 MySQL 协议,可以使用标准 MySQL JDBC 驱动
|
|
|
+6. **白名单配置**:确保应用服务器 IP 已添加到 ADB 实例白名单
|
|
|
+
|
|
|
+## 核心组件说明
|
|
|
+
|
|
|
+### DynamicDataSource
|
|
|
+动态数据源路由类,继承自 `AbstractRoutingDataSource`,根据上下文决定使用哪个数据源。
|
|
|
+
|
|
|
+### DynamicDataSourceContextHolder
|
|
|
+数据源上下文持有者,使用 ThreadLocal 保存当前线程的数据源标识。
|
|
|
+
|
|
|
+### DataSourceAspect
|
|
|
+AOP 切面,自动拦截 `@DataSource` 注解并切换数据源。
|
|
|
+
|
|
|
+### DataSourceConfig
|
|
|
+数据源配置类,定义主数据源、ADB 数据源和动态数据源 Bean。
|
|
|
+
|
|
|
+## 扩展更多数据源
|
|
|
+
|
|
|
+如需添加更多数据源,按以下步骤操作:
|
|
|
+
|
|
|
+1. 在配置文件中添加新数据源的配置
|
|
|
+2. 在 `DataSourceConfig` 中创建新的 DataSource Bean
|
|
|
+3. 在 `DynamicDataSource` 的 targetDataSources 中添加新数据源
|
|
|
+4. 在 `DynamicDataSourceContextHolder` 中添加新的数据源常量
|
|
|
+5. 使用 `@DataSource("新数据源名称")` 注解切换
|
|
|
+
|
|
|
+## 故障排查
|
|
|
+
|
|
|
+### 连接失败
|
|
|
+- 检查 ADB 实例是否正常运行
|
|
|
+- 确认 IP 白名单配置正确
|
|
|
+- 验证用户名密码是否正确
|
|
|
+- 检查网络连通性
|
|
|
+
|
|
|
+### 数据源切换不生效
|
|
|
+- 确认 `@DataSource` 注解使用正确
|
|
|
+- 检查 AOP 是否生效(确认 spring-boot-starter-aop 依赖存在)
|
|
|
+- 查看日志确认数据源切换信息
|
|
|
+
|
|
|
+### 事务问题
|
|
|
+- 多数据源场景下,跨数据源操作不支持分布式事务
|
|
|
+- 如需分布式事务,考虑使用 Seata 等分布式事务框架
|
|
|
+
|
|
|
+## 相关文档
|
|
|
+
|
|
|
+- [阿里云 AnalyticDB 官方文档](https://help.aliyun.com/product/26161.html)
|
|
|
+- [Spring Boot 多数据源配置](https://spring.io/guides)
|
|
|
+
|