Lotes, Buffers e Divisão em Blocos¶
Essas técnicas agrupam trabalho, mas resolvem problemas diferentes:
- processamento em lotes combina operações para amortizar um custo fixo;
- buffering mantém dados temporariamente para desacoplar produtores e consumidores;
- divisão em blocos divide uma entrada grande em partes limitadas.
Um lote no banco pode reduzir viagens de rede. Um buffer de escrita pode suavizar uma rajada curta. Blocos podem limitar a memória no processamento de arquivos. Nada disso elimina a necessidade de semânticas explícitas de correção e falha.
Escolha dois limites¶
Um lote de produção normalmente precisa de tamanho e espera máximos. Apenas o tamanho pode deixar um item de baixo volume esperando para sempre; apenas o tempo pode permitir que uma sobrecarga crie um lote enorme. Buffers também precisam de capacidade e política de overflow: bloquear, rejeitar, descartar ou transferir para armazenamento durável.
static <T> List<List<T>> partition(List<T> values, int size) {
if (size <= 0) throw new IllegalArgumentException("size must be positive");
List<List<T>> chunks = new ArrayList<>();
for (int start = 0; start < values.size(); start += size) {
int end = Math.min(start + size, values.size());
chunks.add(List.copyOf(values.subList(start, end)));
}
return List.copyOf(chunks);
}
O exemplo copia cada bloco para que os chamadores não retenham views apoiadas em uma lista-fonte mutável. Para fontes muito grandes, um iterador ou leitor semelhante a stream evita materializar todos os blocos de uma vez.
Limites de falha e transação¶
Um lote pode ter sucesso parcial. Defina se a operação é atômica, informa resultados por item, repete somente itens que falharam ou compensa trabalho concluído. A execução em lote no banco não forma automaticamente uma transação; uma transação grande aumenta a duração dos locks, o volume de log e o custo de rollback.
Ao repetir um lote, idempotência por item costuma ser mais segura do que tratar toda a coleção como uma operação opaca. Preserve a ordem somente quando ela for um contrato real, pois pode limitar paralelismo e recuperação.
Verificações operacionais¶
- meça throughput e latência de ponta a ponta, inclusive o tempo no buffer;
- exponha profundidade da fila, tamanho do lote, idade do item mais antigo e rejeições;
- teste um item, limites exatos, bloco final parcial, sobrecarga e encerramento;
- descarregue ou transfira de forma durável o trabalho aceito no encerramento gracioso;
- evite acúmulo ilimitado quando o consumidor ficar mais lento que o produtor.