1. Batch策略概述:为什么需要Batch?
大家好,我是你们的老朋友。今天咱们聊聊Batch策略。
说实话,我刚入行那会儿,对Batch这玩意儿完全没概念。那时候写代码,就是一条一条处理数据。后来系统扛不住了,才意识到——嗯,单条处理,其实是个坑。
从单条处理到批量处理的演进
先看一个最简单的场景。你有个服务,需要往数据库里写1000条记录。
单条处理长什么样?
for (Record record : records) {
insertIntoDB(record); // 每次一条,循环1000次
}
这代码看着挺清爽,对吧?但问题来了——每次insert,都要建立一次网络连接、发送一次SQL、等待一次ACK。1000次循环,就是1000次网络往返。
我当年在一个电商项目中就吃过这个亏。订单系统每天几百万条数据入库,单条插入,数据库连接池直接被打满,CPU飙升到90%。老板站在我身后,那眼神……你们懂的。
改成批量处理呢?
List<Record> batch = new ArrayList<>();
for (Record record : records) {
batch.add(record);
if (batch.size() >= 100) {
batchInsertIntoDB(batch); // 攒够100条,一次写入
batch.clear();
}
}
网络往返从1000次降到了10次。效果立竿见影。
Batch的核心价值
说白了,Batch策略就干两件事:降低IO,提升吞吐。
| 维度 | 单条处理 | 批量处理 |
|---|---|---|
| 网络IO次数 | N次 | N/BatchSize次 |
| 磁盘IO次数 | N次刷盘 | N/BatchSize次刷盘 |
| 系统吞吐 | 低(受限于IO延迟) | 高(IO合并后效率倍增) |
| 资源消耗 | 高(频繁创建/销毁连接) | 低(连接复用) |
你想想看,IO是计算机系统里最慢的环节。内存操作是纳秒级,磁盘IO是毫秒级,网络IO更慢。每次IO,CPU都得等着。Batch的本质,就是把多次小IO合并成一次大IO,让CPU少等一会儿。
核心公式:
吞吐量 ≈ 单次处理数据量 / 单次IO耗时
BatchSize越大,单次IO的“性价比”越高。但也不是越大越好——后面我会讲怎么踩这个平衡点。
Batch适用的场景
不是所有场景都适合Batch。我个人习惯,遇到以下情况会优先考虑Batch:
- 数据写入类操作:数据库insert、日志写入、消息队列生产
- 网络调用类操作:RPC调用、HTTP请求(如果能合并的话)
- 文件处理类操作:读写文件、数据导出
- 计算密集型操作:批量计算、批量校验
但有些场景,Batch反而坏事。比如实时性要求极高的场景——你攒100条再发,用户等得起吗?
避坑指南:
我曾经在一个实时风控系统里强行用Batch,结果用户刷了卡,风控结果5秒后才返回。老板差点让我卷铺盖走人。记住:Batch是吞吐和延迟的trade-off,不是银弹。
Batch策略的核心维度
设计Batch策略时,我一般会关注三个维度:
- Batch大小:攒多少条数据再处理?100条?1000条?
- Batch时间:最多等多久?1秒?100毫秒?
- Batch策略:满了就发?还是定时发?还是混合策略?
这三个维度,就像三根绳子,你得找到那个平衡点。后面几章我会详细拆解。
知识体系总览
下面这张图,是我自己总结的Batch策略知识体系。你看一眼,心里就有谱了。
我的经验:
刚开始做Batch时,别想太复杂。先定一个固定大小(比如100条),跑起来看看效果。性能瓶颈在哪,再针对性调。我见过太多人一上来就搞动态调整、自适应算法,结果系统还没上线,自己先被搞晕了。
好了,这一章就聊到这儿。Batch的核心思想其实很简单——别让CPU闲着,别让IO浪费。后面的章节,我会带你一步步把Batch玩出花来。
想要更多资料,联系可可