erp-java/docs/database-split-design.md

221 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 微服务数据库拆分设计方案
## 1. 现状分析
### 当前PHP单库结构
```
erp_db (单库,所有表)
├── 用户相关表
│ ├── users
│ ├── roles
│ ├── permissions
│ └── user_roles
├── 订单相关表
│ ├── orders
│ ├── order_items
│ └── order_operations
├── 商品相关表
│ ├── goods
│ ├── brands
│ ├── suppliers
│ └── categories
├── 库存相关表
│ ├── stock
│ └── stock_logs
├── 财务相关表
│ ├── finance_transactions
│ └── account_balances
└── 其他业务表
├── files
├── notifications
├── tenants
└── system_configs
```
## 2. 拆分原则
### 2.1 按业务领域拆分
- 每个微服务拥有独立的数据库
- 数据库按业务领域划分
- 服务间通过API或消息队列通信
### 2.2 数据所有权原则
- 谁创建数据,谁拥有数据
- 其他服务通过服务间调用访问数据
- 避免直接数据库访问
### 2.3 数据一致性策略
- 强一致性分布式事务Seata
- 最终一致性:消息队列+事件驱动
- 数据同步CDC变更数据捕获
## 3. 拆分方案
### 3.1 数据库拆分设计
| 微服务 | 数据库名 | 包含表 | 数据量预估 |
|--------|----------|--------|------------|
| **用户服务** | `user_db` | users, roles, permissions, user_roles, login_logs | 10万+ |
| **订单服务** | `order_db` | orders, order_items, order_operations, order_logs | 100万+ |
| **商品服务** | `product_db` | goods, brands, suppliers, categories, product_prices | 5万+ |
| **库存服务** | `inventory_db` | stock, stock_logs, warehouses, locations | 50万+ |
| **财务服务** | `finance_db` | finance_transactions, account_balances, invoices, payments | 50万+ |
| **文件服务** | `file_db` | files, file_groups, file_metadata | 100万+ |
| **租户服务** | `tenant_db` | tenants, packages, tenant_features | 1万+ |
| **通知服务** | `notification_db` | notifications, notification_templates, message_queue | 100万+ |
| **配置服务** | `config_db` | system_configs, config_groups, config_history | 1万+ |
### 3.2 共享数据表
| 表名 | 用途 | 归属服务 | 访问方式 |
|------|------|----------|----------|
| **字典表** | 通用字典数据 | 配置服务 | API调用 |
| **地区表** | 省市区数据 | 配置服务 | API调用 |
| **日志表** | 操作日志 | 日志服务 | 消息队列 |
## 4. 迁移策略
### 4.1 分阶段迁移
```
阶段1: 数据库逻辑拆分 (本周)
- 创建独立数据库
- 迁移表结构
- 保持PHP系统正常运行
阶段2: 数据同步 (下周)
- 建立数据同步通道
- 实时同步关键数据
- 验证数据一致性
阶段3: 服务切换 (下下周)
- 逐步切换服务到新数据库
- 监控数据一致性
- 回滚机制准备
阶段4: 完全切换 (下下下周)
- 所有服务使用新数据库
- 停用旧数据库
- 清理同步通道
```
### 4.2 数据同步方案
#### 方案1: 双写模式
```
PHP应用 → 同时写入 → 旧数据库 + 新数据库
数据一致性校验
```
#### 方案2: CDC同步模式
```
旧数据库 → Debezium CDC → Kafka → 新数据库
(变更数据捕获) (消息队列)
```
#### 方案3: 应用层同步
```
PHP应用 → 写入旧数据库 → 同步服务 → 写入新数据库
```
## 5. 技术实现
### 5.1 数据库连接配置
```yaml
# 用户服务配置
spring:
datasource:
url: jdbc:mysql://mysql-server:3306/user_db
username: user_service
password: ${DB_PASSWORD}
# 订单服务配置
spring:
datasource:
url: jdbc:mysql://mysql-server:3306/order_db
username: order_service
password: ${DB_PASSWORD}
```
### 5.2 数据同步配置
```yaml
# Debezium CDC配置
debezium:
connector:
class: io.debezium.connector.mysql.MySqlConnector
database.hostname: mysql-server
database.port: 3306
database.user: cdc_user
database.password: ${CDC_PASSWORD}
database.server.id: 184054
database.server.name: erp_cdc
table.include.list: erp_db.*
database.history.kafka.bootstrap.servers: kafka:9092
database.history.kafka.topic: dbhistory.erp
```
### 5.3 服务间数据访问
```java
// 订单服务需要用户信息时调用用户服务API
@FeignClient(name = "user-service")
public interface UserServiceClient {
@GetMapping("/api/users/{userId}")
UserDTO getUserById(@PathVariable Long userId);
}
// 而不是直接查询用户数据库
```
## 6. 风险与应对
### 6.1 数据一致性风险
- **风险**: 拆分过程中数据不一致
- **应对**: 实时数据校验,不一致时告警并自动修复
### 6.2 性能风险
- **风险**: 服务间调用增加延迟
- **应对**: 缓存常用数据,批量查询优化
### 6.3 复杂性风险
- **风险**: 系统复杂度增加
- **应对**: 完善监控告警,自动化运维
## 7. 实施计划
### 7.1 时间计划
```
第1周: 方案设计 + 环境准备
第2周: 数据库创建 + 表结构迁移
第3周: 数据同步通道建立
第4周: 服务逐步切换
第5周: 完全切换 + 验证
```
### 7.2 团队分工
- **DBA团队**: 数据库拆分、备份恢复
- **开发团队**: 服务改造、API适配
- **运维团队**: 监控部署、性能优化
- **测试团队**: 数据一致性验证
## 8. 成功指标
### 8.1 技术指标
- 数据一致性: 99.99%
- 服务响应时间: < 200ms (P95)
- 系统可用性: 99.9%
### 8.2 业务指标
- 零数据丢失
- 业务无感知切换
- 性能不下降
---
**下一步行动:**
1. 评审设计方案
2. 准备数据库环境
3. 开始阶段1实施