302 lines
8.2 KiB
Markdown
302 lines
8.2 KiB
Markdown
# 充值记录服务优化说明
|
|
|
|
## 优化概述
|
|
|
|
本次优化主要针对充值记录服务进行了两个重要改进:
|
|
|
|
1. **统一钱包余额更新逻辑** - 使用钱包聚合服务的充值方法
|
|
2. **添加事务支持** - 为所有充值相关方法添加事务保护
|
|
|
|
## 优化内容
|
|
|
|
### 1. 统一钱包余额更新逻辑
|
|
|
|
#### 问题分析
|
|
之前的充值记录服务直接操作钱包仓储来更新余额,存在以下问题:
|
|
- 代码重复:钱包余额更新逻辑在多个地方重复实现
|
|
- 维护困难:余额更新逻辑变更需要在多个地方修改
|
|
- 一致性风险:不同服务可能使用不同的余额更新逻辑
|
|
|
|
#### 解决方案
|
|
修改充值记录服务,使用钱包聚合服务的 `Recharge` 方法来更新钱包余额:
|
|
|
|
**修改的方法:**
|
|
- `TransferRecharge` - 对公转账充值
|
|
- `GiftRecharge` - 赠送充值
|
|
- `HandleAlipayPaymentSuccess` - 支付宝支付成功回调处理
|
|
|
|
**修改前:**
|
|
```go
|
|
// 直接操作钱包仓储
|
|
w.AddBalance(amount)
|
|
ok, err := s.walletRepo.UpdateBalanceWithVersion(ctx, w.ID, w.Balance.String(), w.Version)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !ok {
|
|
return nil, fmt.Errorf("高并发下充值失败,请重试")
|
|
}
|
|
```
|
|
|
|
**修改后:**
|
|
```go
|
|
// 使用钱包聚合服务
|
|
err = s.walletService.Recharge(ctx, userID, amount)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
```
|
|
|
|
#### 优势
|
|
- **代码复用**:统一使用钱包聚合服务的余额更新逻辑
|
|
- **维护性**:余额更新逻辑变更只需在一个地方修改
|
|
- **一致性**:确保所有充值方式使用相同的余额更新逻辑
|
|
- **可测试性**:可以独立测试钱包聚合服务的余额更新逻辑
|
|
|
|
### 2. 添加事务支持
|
|
|
|
#### 问题分析
|
|
充值相关方法执行多个数据库操作:
|
|
|
|
**TransferRecharge 方法:**
|
|
1. 创建充值记录
|
|
2. 更新钱包余额
|
|
3. 更新充值记录状态为成功
|
|
|
|
**GiftRecharge 方法:**
|
|
1. 创建充值记录
|
|
2. 更新钱包余额
|
|
|
|
**HandleAlipayPaymentSuccess 方法:**
|
|
1. 更新支付宝订单状态
|
|
2. 更新充值记录状态
|
|
3. 更新钱包余额
|
|
|
|
如果任何一步失败,可能导致数据不一致:
|
|
- 充值记录已创建,但钱包余额未更新
|
|
- 支付宝订单已更新,但充值记录未更新
|
|
- 充值记录已更新,但钱包余额未更新
|
|
- 重复处理导致数据异常
|
|
|
|
#### 解决方案
|
|
为所有充值相关方法添加事务支持:
|
|
|
|
**添加事务的方法:**
|
|
- `TransferRecharge` - 对公转账充值
|
|
- `GiftRecharge` - 赠送充值
|
|
- `HandleAlipayPaymentSuccess` - 支付宝支付成功回调处理
|
|
|
|
**修改前:**
|
|
```go
|
|
// 逐个执行更新操作,无事务保护
|
|
// TransferRecharge 示例
|
|
createdRecord, err := s.rechargeRecordRepo.Create(ctx, *rechargeRecord)
|
|
err = s.walletService.Recharge(ctx, userID, amount)
|
|
err = s.rechargeRecordRepo.Update(ctx, createdRecord)
|
|
|
|
// GiftRecharge 示例
|
|
createdRecord, err := s.rechargeRecordRepo.Create(ctx, *rechargeRecord)
|
|
err = s.walletService.Recharge(ctx, userID, amount)
|
|
|
|
// HandleAlipayPaymentSuccess 示例
|
|
alipayOrder.MarkSuccess(tradeNo, "", "", amount, amount)
|
|
err = s.alipayOrderRepo.Update(ctx, *alipayOrder)
|
|
// ... 其他更新操作
|
|
```
|
|
|
|
**修改后:**
|
|
```go
|
|
// 在事务中执行所有更新操作
|
|
// TransferRecharge 示例
|
|
err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error {
|
|
record, err := s.rechargeRecordRepo.Create(txCtx, *rechargeRecord)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
createdRecord = record
|
|
|
|
err = s.walletService.Recharge(txCtx, userID, amount)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
createdRecord.MarkSuccess()
|
|
err = s.rechargeRecordRepo.Update(txCtx, createdRecord)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
// GiftRecharge 示例
|
|
err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error {
|
|
record, err := s.rechargeRecordRepo.Create(txCtx, *rechargeRecord)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
createdRecord = record
|
|
|
|
err = s.walletService.Recharge(txCtx, userID, amount)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
// HandleAlipayPaymentSuccess 示例
|
|
err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error {
|
|
// 更新支付宝订单状态为成功
|
|
alipayOrder.MarkSuccess(tradeNo, "", "", amount, amount)
|
|
err := s.alipayOrderRepo.Update(txCtx, *alipayOrder)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 更新充值记录状态为成功
|
|
rechargeRecord.MarkSuccess()
|
|
err = s.rechargeRecordRepo.Update(txCtx, rechargeRecord)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 使用钱包聚合服务更新钱包余额
|
|
err = s.walletService.Recharge(txCtx, rechargeRecord.UserID, amount)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
```
|
|
|
|
#### 优势
|
|
- **数据一致性**:确保所有操作要么全部成功,要么全部回滚
|
|
- **幂等性**:防止重复处理导致的数据不一致
|
|
- **错误处理**:统一的错误处理和回滚机制
|
|
- **业务完整性**:保证充值记录和钱包余额状态一致
|
|
- **原子性**:所有相关操作作为一个原子单元执行
|
|
|
|
## 技术实现
|
|
|
|
### 1. 依赖注入更新
|
|
|
|
**充值记录服务构造函数:**
|
|
```go
|
|
func NewRechargeRecordService(
|
|
rechargeRecordRepo repositories.RechargeRecordRepository,
|
|
alipayOrderRepo repositories.AlipayOrderRepository,
|
|
walletRepo repositories.WalletRepository,
|
|
walletService WalletAggregateService, // 新增
|
|
txManager *database.TransactionManager, // 新增
|
|
logger *zap.Logger,
|
|
) RechargeRecordService
|
|
```
|
|
|
|
**服务结构体:**
|
|
```go
|
|
type RechargeRecordServiceImpl struct {
|
|
rechargeRecordRepo repositories.RechargeRecordRepository
|
|
alipayOrderRepo repositories.AlipayOrderRepository
|
|
walletRepo repositories.WalletRepository
|
|
walletService WalletAggregateService // 新增
|
|
txManager *database.TransactionManager // 新增
|
|
logger *zap.Logger
|
|
}
|
|
```
|
|
|
|
### 2. 事务管理
|
|
|
|
使用 `shared/database.TransactionManager` 进行事务管理:
|
|
- 自动事务开始和提交
|
|
- 异常时自动回滚
|
|
- 支持事务超时和重试
|
|
- 提供事务统计和监控
|
|
|
|
### 3. 错误处理
|
|
|
|
- 保持原有的错误处理机制
|
|
- 事务失败时自动回滚所有更改
|
|
- 详细的错误日志记录
|
|
- 幂等性检查防止重复处理
|
|
|
|
## 影响评估
|
|
|
|
### 1. 向后兼容性
|
|
- ✅ 应用服务层接口保持不变
|
|
- ✅ 对调用方完全透明
|
|
- ✅ 保持原有的错误处理机制
|
|
|
|
### 2. 性能影响
|
|
- ✅ 事务开销可控,仅在支付宝回调时使用
|
|
- ✅ 减少代码重复,提高执行效率
|
|
- ✅ 统一余额更新逻辑,减少数据库操作
|
|
|
|
### 3. 数据一致性
|
|
- ✅ 显著提高数据一致性
|
|
- ✅ 防止部分更新导致的数据不一致
|
|
- ✅ 支持幂等性处理
|
|
|
|
### 4. 维护性
|
|
- ✅ 代码更加清晰和易于维护
|
|
- ✅ 减少重复代码
|
|
- ✅ 统一的错误处理机制
|
|
|
|
## 测试建议
|
|
|
|
### 1. 单元测试
|
|
- 测试钱包聚合服务的 `Recharge` 方法
|
|
- 测试充值记录服务的各个方法
|
|
- 测试事务回滚机制
|
|
|
|
### 2. 集成测试
|
|
- 测试完整的支付宝充值流程
|
|
- 测试事务失败时的回滚机制
|
|
- 测试重复回调的处理
|
|
|
|
### 3. 压力测试
|
|
- 测试高并发下的充值处理
|
|
- 测试事务超时和重试机制
|
|
- 测试数据库连接池的使用
|
|
|
|
## 监控建议
|
|
|
|
### 1. 业务监控
|
|
- 监控充值成功率
|
|
- 监控事务执行时间
|
|
- 监控事务回滚次数
|
|
|
|
### 2. 技术监控
|
|
- 监控数据库连接池使用情况
|
|
- 监控事务超时情况
|
|
- 监控错误率和异常情况
|
|
|
|
## 后续优化
|
|
|
|
### 1. 事件驱动
|
|
考虑使用事件驱动架构来处理充值成功后的业务逻辑:
|
|
- 充值成功事件
|
|
- 余额变更事件
|
|
- 通知事件
|
|
|
|
### 2. 缓存优化
|
|
- 对频繁查询的充值记录添加缓存
|
|
- 对钱包余额添加缓存
|
|
- 实现缓存一致性机制
|
|
|
|
### 3. 异步处理
|
|
- 将非关键操作异步化
|
|
- 使用消息队列处理充值回调
|
|
- 实现重试机制
|
|
|
|
## 总结
|
|
|
|
本次优化通过统一钱包余额更新逻辑和添加事务支持,显著提高了充值记录服务的:
|
|
|
|
1. **代码质量** - 减少重复代码,提高可维护性
|
|
2. **数据一致性** - 确保业务操作的原子性
|
|
3. **错误处理** - 统一的错误处理和回滚机制
|
|
4. **可测试性** - 更好的单元测试和集成测试支持
|
|
|
|
这些改进为后续的功能扩展和维护奠定了良好的基础。 |