DATABASE_ARCHITECTURE.md 6.7 KB

数据库架构设计说明

概述

zsElectric-OpenApi 开放平台采用双数据库架构,将开放平台数据和业务系统数据进行物理隔离,同时通过动态数据源实现跨数据库访问。

数据库设计

1. 开放平台独立数据库 (zs_electric_openapi)

这是开放平台专用的数据库,存储以下数据:

  • 应用管理数据: 第三方应用信息(AppId、AppSecret、权限等)
  • API调用日志: 所有第三方API调用记录
  • 访问控制数据: IP白名单、调用频率限制等

优点:

  • 数据隔离,互不影响
  • 独立备份和恢复
  • 便于权限管控
  • 性能优化

2. 业务系统数据库 (zs_electric)

这是原有的业务系统数据库,开放平台通过动态数据源只读访问该数据库:

  • 充电站信息
  • 充电订单数据
  • 用户数据
  • 其他业务数据

访问方式:

  • 只读访问,确保业务系统数据安全
  • 通过 @DS("business") 注解指定数据源
  • 使用独立的Service层封装业务数据访问

数据源配置

开发环境 (application-dev.yml)

spring:
  datasource:
    dynamic:
      primary: openapi  # 默认使用开放平台数据库
      strict: false
      datasource:
        # 开放平台独立数据库
        openapi:
          url: jdbc:mysql://localhost:3306/zs_electric_openapi
          username: root
          password: root

        # 业务系统数据库(只读)
        business:
          url: jdbc:mysql://localhost:3306/zs_electric
          username: root
          password: root

生产环境 (application-prod.yml)

spring:
  datasource:
    dynamic:
      primary: openapi
      datasource:
        openapi:
          url: jdbc:mysql://prod-db-host:3306/zs_electric_openapi
          username: openapi_user  # 专用账号,仅拥有openapi数据库权限
          password: xxxxx

        business:
          url: jdbc:mysql://prod-db-host:3306/zs_electric
          username: business_readonly_user  # 只读账号
          password: xxxxx

数据源使用方式

1. 使用默认数据源(openapi)

对于开放平台自己的实体类(如AppInfo、ApiLog),不需要任何注解:

@Data
@TableName("openapi_app_info")
public class AppInfo {
    // 使用默认数据源(openapi)
}

@Mapper
public interface AppInfoMapper extends BaseMapper<AppInfo> {
    // 使用默认数据源(openapi)
}

@Service
public class AppInfoService extends ServiceImpl<AppInfoMapper, AppInfo> {
    // 使用默认数据源(openapi)
}

2. 使用业务数据库(business)

对于需要访问业务系统数据的实体类,使用 @DS("business") 注解:

@Data
@TableName("charging_station")
public class ChargingStation {
    // 实体类定义
}

@Mapper
@DS("business")  // 指定使用业务数据库
public interface ChargingStationMapper extends BaseMapper<ChargingStation> {
}

@Service
@DS("business")  // Service层也指定
public class ChargingStationService extends ServiceImpl<ChargingStationMapper, ChargingStation> {
    public List<ChargingStation> getActiveStations() {
        // 查询业务数据库
        return lambdaQuery()
            .eq(ChargingStation::getStatus, 1)
            .list();
    }
}

3. Controller层调用

Controller层直接调用对应的Service即可,数据源切换由Service层的注解控制:

@RestController
@RequestMapping("/api/v1/charging")
@RequiredArgsConstructor
public class ChargingController {

    private final ChargingStationService chargingStationService;  // 使用business数据源
    private final ApiLogMapper apiLogMapper;  // 使用openapi数据源

    @GetMapping("/stations")
    public Result<Map<String, Object>> getStationList() {
        // 调用业务系统数据
        List<ChargingStation> stations = chargingStationService.getActiveStations();

        // 记录到开放平台数据库
        ApiLog apiLog = new ApiLog();
        // ... 设置日志信息
        apiLogMapper.insert(apiLog);

        return Result.success(stations);
    }
}

代码结构

com.zsElectric.openapi/
├── entity/              # 开放平台实体(使用openapi数据源)
│   ├── AppInfo.java
│   └── ApiLog.java
├── mapper/              # 开放平台Mapper(使用openapi数据源)
│   ├── AppInfoMapper.java
│   └── ApiLogMapper.java
├── business/            # 业务系统相关(使用business数据源)
│   ├── entity/
│   │   ├── ChargingStation.java
│   │   └── ChargingOrder.java
│   ├── mapper/
│   │   ├── ChargingStationMapper.java
│   │   └── ChargingOrderMapper.java
│   └── service/
│       ├── ChargingStationService.java
│       └── ChargingOrderService.java
└── controller/          # 控制器
    ├── ChargingController.java
    └── OrderController.java

数据安全

1. 权限控制

生产环境应为不同的数据库创建专门的账号:

-- 开放平台数据库账号
CREATE USER 'openapi_user'@'%' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON zs_electric_openapi.* TO 'openapi_user'@'%';

-- 业务系统只读账号
CREATE USER 'business_readonly_user'@'%' IDENTIFIED BY 'password';
GRANT SELECT ON zs_electric.* TO 'business_readonly_user'@'%';

2. 访问限制

  • 开放平台只能只读访问业务数据库
  • 不允许开放平台修改业务系统数据
  • 所有的写操作都在开放平台自己的数据库中

3. 监控审计

  • 所有API调用都记录日志
  • 可以追踪每个应用的访问记录
  • 异常访问及时发现和处理

优势总结

  1. 数据隔离: 开放平台和业务系统完全解耦
  2. 安全性高: 业务系统数据不会被第三方误操作
  3. 可维护性强: 便于独立升级和维护
  4. 性能优化: 可以针对不同的数据库进行优化
  5. 灵活扩展: 未来可以轻松添加更多数据源

常见问题

Q1: 为什么不直接使用业务数据库?

A: 考虑到安全性、性能和可维护性,开放平台应该有独立的数据库,同时通过动态数据源访问业务数据。

Q2: 开放平台能否写业务数据库?

A: 不能。生产环境应该使用只读账号访问业务数据库,所有写操作都在开放平台自己的数据库中。

Q3: 如何在同一个方法中使用多个数据源?

A: 不能在同一个方法中直接切换数据源。需要将不同数据源的操作拆分到不同的Service中。

Q4: 性能如何?

A: 动态数据源切换的性能损耗非常小,可以忽略不计。通过连接池管理,可以保证高性能。

Q5: 如何处理事务?

A: 如果需要跨数据源事务,建议使用分布式事务方案,如Seata。但对于开放平台场景,通常不需要跨数据源事务。