Tenho cenário semelhante, mas em menor escala, porém mesmo assim uma grande volumetria - 400~600 tps em média no tópico Kafka. No passado, o workers inseriam do jeito tradicional, com insert into table(....) values (...) ou update table set.... Esse algoritmo ruim, não dava conta de sincronizar, estava sempre com lag, e ao escalar os workers, começava a catástrofe do ambiente. O alto número do workers fazia o DB ficar sempre com carga excessiva, acima de 80% de CPU.
Fiz um mudança pequena, no lugar de inserir/atualizar com comandos SQL cada mensagem recebida do tópico (q demanda mais cpu pra parser no db), passei a fazer bulk upsert da seguinte forma:
- Agrupar mensagens do tópico em pacotes antes de enviar pro DB. Fiz duas regras de corte do pacote: 5 mil mensagens, ou 10 segundos sem receber mensagens.
- Criar uma temporary table copiada da original (
create temp table nome_temporario on commit drop as table nome_original with no data) - Inserir o pacote de mensagens agrupadas com o com
copy from stdin... - Ao final copiar dados da tabela temporária para original com comando de upsert:
insert into tabela(campos) values (valores) on conflict (campo pk) do update campos. (Com índice único, pois tb tenho situação parecida de duplicidades de msgs). - Tudo isso é uma transaction.l
Com isso, reduzi o uso de CPU de 85% pra 13~15% em média, e sem lag.
Hj o db é um aurora postgresql r6g.large (2 cpu x 16 ram), e o worker é apenas uma instância de ecs com 0.5 cpu x 1 gb de ram (e até poderia ser menor, mas tem outras coisas internas q não vem ao caso aqui).
A otimização do worker, normalizou o resto do ambiente, apis q dependem desse db obviamente passaram a responder mais rápido, e de propósito não deixo mais o worker escalar pra não degradar o ambiente, embora com o novo algoritmo não deva ser problema processar umas 500 milhões de msg por dia no mesmo hardware.
Pro seu cenário de big data sobre telemetria de aplicações, tb julgo correta a mudança pra um DB colunar pra otimizar as consultas com agregações, só queria compartilhar essa solução de carga de alto volume de dados em postgresql após ler essa parte em específico da sua saga. Pretendo montar um post para explicar em maiores detalhes.
Pra quem se interessar, aqui tem alguns benchmarks e exemplos do que venho preparando.
Valeuuu, e novamente parabéns pela história e por compartilhar.