23 pontos por xguru 2023-04-13 | 6 comentários | Compartilhar no WhatsApp
  • Removemos o RabbitMQ e o substituímos por uma fila no PostgresDB usando SQL
  • A troca levou cerca de meio dia, e o código-fonte ficou 580 linhas menor
  • Mais importante ainda: a estabilidade e a resiliência melhoraram bastante
  • Não se trata de criticar sistemas de fila como o RabbitMQ, mas simplesmente de um esforço para manter tudo mais simples
    • A Prequel, autora deste texto, é um produto que ajuda empresas B2B SaaS a sincronizar com os bancos de dados de seus clientes por meio de pipelines de dados em larga escala
  • A arquitetura era composta por RabbitMQ + AQMP + Helm + wrapper em GoLang, e funcionou bem por um tempo, mas os problemas começaram a aparecer
    • O envio das mensagens passou a sofrer atrasos longos demais, fazendo com que mensagens fossem canceladas
    • Como o consumer fazia prefetch das mensagens, surgiu a situação em que a próxima mensagem ficava retida até a conclusão da mensagem atual
    • Se esse prefetch fosse definido como 0, ele se tornava infinito, então não era possível desativá-lo
    • O problema acontecia porque os trabalhos que recebiam e processavam as mensagens geralmente eram tarefas de longa duração (transferência de dados)
  • Eles entenderam exatamente o que estava acontecendo, mas não havia uma forma imediata de corrigir isso. Como o problema afetava clientes em produção, esperar não era uma opção
  • Por isso, passaram a operar com um modelo simples de leitura e escrita no Postgres usando uma única tabela
    • Locks em nível de linha para leitura/escrita garantem que apenas um consumer leia cada trabalho
    • É absurdamente simples, mas está funcionando perfeitamente
  • Há também a vantagem de o estado da aplicação não ficar dividido entre RabbitMQ e Postgres, mas consolidado em um único lugar

6 comentários

 
galadbran 2023-04-15

Eu também implementei diretamente uma fila no mysql com row level lock, e isso tem funcionado bem em produção há anos.
O que eu queria, simplesmente, era oferecer uma funcionalidade parecida com fila para vários workers, armazenando junto o payload com estados dentro da fila como em espera/em andamento/falha (se concluir, é removido).

Pelo fato de, no texto, terem feito a transição do rabbitmq para o banco de dados em pouco tempo, imagino que isso se deva a não precisarem necessariamente da generalidade de um serviço de filas dedicado nem dos seus diversos recursos e possibilidades de configuração.

 
pseudojo 2023-04-15

Parece que o problema surgiu por um descompasso entre o envio do ACK manual e a transação do banco de dados,
e é interessante que eles tenham resolvido isso não com engenharia, mas removendo o RabbitMQ.
O RabbitMQ provavelmente não teve culpa...

 
laracool 2023-04-13

https://news.ycombinator.com/item?id=35526846
Há muitas opiniões nos comentários.

 
dddddd 2023-04-13

Também existe algo como isto, que funciona de forma semelhante: https://github.com/pjongy/jasyncq

 
laracool 2023-04-13

Parece que há possibilidade de ser feito select ao mesmo tempo; fiquei curioso sobre como isso foi resolvido.

 
dddddd 2023-04-13

Parece que está escrito row level lock.