01
A chave decide quem espera por quem
Em qualquer sistema de log particionado, seja Kafka, Kinesis, Pub/Sub com chave de ordenação ou uma fila caseira em cima do Postgres, a chave cumpre duas funções ao mesmo tempo e quase todo desenho só considera uma delas. A primeira é a que aparece na documentação: mensagens com a mesma chave vão para a mesma partição e por isso são entregues na ordem em que foram produzidas. A segunda é a que aparece no incidente: mensagens com chaves diferentes que caem na mesma partição por acaso do hash passam a compartilhar uma fila serial e uma sorte comum. A chave não define apenas o que fica ordenado, define quem fica preso atrás de quem.
É por isso que a pergunta certa na hora de escolher a chave não é qual campo distribui melhor, e sim qual é a menor unidade que realmente precisa de ordem. Se o requisito é que os eventos de uma conversa sejam processados na sequência, a unidade é a conversa e não o cliente. Se a chave for o identificador do cliente, todas as conversas daquele cliente ficam serializadas por uma exigência que o negócio nunca fez, e a fila herda um gargalo artificial. A regra prática que fecha essa parte é direta: ordenar mais do que o necessário nunca é neutro, é sempre capacidade jogada fora e latência transferida para quem não pediu.
CHAVE = tenant_id (ordem alem do necessario)
P0 [tenant-A x 70000 ...........................] <- 18 min de backlog
P1 [tenant-C][tenant-F][tenant-J] <- vazia em segundos
P2 [tenant-B][tenant-D] <- vazia em segundos
P3 [tenant-E][tenant-G][tenant-H] <- vazia em segundos
^ tenant-K caiu no hash de P0 e espera 18 min
por um backlog que nao e dele
CHAVE = tenant_id + conversation_id (ordem no que o negocio exige)
P0 [A/c1][K/c9][A/c4][C/c2]
P1 [A/c2][B/c7][A/c5][K/c3]
P2 [A/c3][D/c1][F/c8][A/c6]
P3 [A/c7][E/c2][A/c8][J/c4]
^ o volume do tenant-A continua grande, mas agora
se espalha, e nenhum outro tenant fica atras deleVale separar dois fenômenos que costumam ser tratados como um só porque produzem o mesmo sintoma no painel. Desequilíbrio de partição é quando o hash distribui mal e uma partição recebe mais mensagens que as outras, e ele se corrige com mais entropia na chave. Bloqueio de cabeça de fila é quando uma única mensagem lenta ou envenenada trava tudo que está atrás dela na mesma partição, e ele não se corrige com entropia nenhuma, porque o problema não é o volume e sim a serialização. Sistemas reais quase sempre têm os dois, e a correção de um não ajuda em nada no outro.