这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
批量处理
从逐条处理到批量处理
还记得我最初的实现吗?
每次取消订单都要:
- 更新订单状态(数据库写入)
- 释放库存(数据库写入)
- 发送通知(HTTP 请求)
- 记录日志
如果有 1000 个订单要取消,那就是 3000 次数据库写入和 1000 次 HTTP 请求!
逐条处理的性能瓶颈:
数据库 I/O:3000 次
网络 I/O:1000 次
总耗时:~15 秒批量处理的优势
性能对比
| 维度 | 逐条处理 | 批量处理 | 提升 |
|---|---|---|---|
| 数据库 I/O | 3000 次 | 100 次 | 30x |
| 网络往返 | 1000 次 | 10 次 | 100x |
| 总耗时 | 15 秒 | 2 秒 | 7.5x |
| 连接占用 | 高 | 低 | - |
原理
逐条处理:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 任务 1 │───►│ 处理任务 │───►│ 写数据库 │
└─────────┘ └─────────┘ └─────────┘
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 任务 2 │───►│ 处理任务 │───►│ 写数据库 │
└─────────┘ └─────────┘ └─────────┘
...
批量处理:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 任务 1 │────│ │ │ │
├─────────┤ │ 批量处理 │───►│ 批量写入 │
│ 任务 2 │────│ │ │ │
├─────────┤ └─────────┘ └─────────┘
│ 任务 3 │────│
└─────────┘ │
... │
│
▼
一次处理完成批量处理实现
数据库批量更新
批量查询
批量插入
批量处理的注意事项
1. 批量大小的选择
批量大小建议:
| 场景 | 批量大小 | 理由 |
|---|---|---|
| 简单数据库更新 | 100~500 | 数据库连接池限制 |
| 复杂业务逻辑 | 10~50 | 避免单个请求超时 |
| 外部 API 调用 | 5~20 | 避免超时和限流 |
| 大量数据导入 | 1000~5000 | 最大化吞吐量 |
2. 事务管理
3. 错误处理
批量处理的完整示例
想一想
思考 1
批量处理时,如果部分任务失败,应该如何处理?
参考答案
问题分析:
批量处理中,如果 100 个任务中有 5 个失败,如何处理?
三种策略:
策略 1:全部失败回滚
优点: 数据一致性好 缺点: 一个失败影响全部
策略 2:部分失败跳过
优点: 不会影响成功的任务 缺点: 需要额外处理失败任务
策略 3:分组处理
优点: 平衡了并发控制和故障隔离 缺点: 实现较复杂
最佳实践建议:
- 允许部分失败:对于非关键任务
- 分组处理:对于大批量任务
- 全部回滚:对于强一致性要求