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策略时,我一般会关注三个维度:

  1. Batch大小:攒多少条数据再处理?100条?1000条?
  2. Batch时间:最多等多久?1秒?100毫秒?
  3. Batch策略:满了就发?还是定时发?还是混合策略?

这三个维度,就像三根绳子,你得找到那个平衡点。后面几章我会详细拆解。

知识体系总览

下面这张图,是我自己总结的Batch策略知识体系。你看一眼,心里就有谱了。

Batch策略核心 Batch大小 Batch时间 Batch策略 固定条数 动态调整 固定间隔 最大等待 满则发 定时+定量 核心价值:降低IO × 提升吞吐 本质:用空间换时间,用延迟换吞吐

我的经验:

刚开始做Batch时,别想太复杂。先定一个固定大小(比如100条),跑起来看看效果。性能瓶颈在哪,再针对性调。我见过太多人一上来就搞动态调整、自适应算法,结果系统还没上线,自己先被搞晕了。

好了,这一章就聊到这儿。Batch的核心思想其实很简单——别让CPU闲着,别让IO浪费。后面的章节,我会带你一步步把Batch玩出花来。

想要更多资料,联系可可