O uso de notificações por eventos, que discutimos em um post anterior, permite o desenvolvimento de soluções elegantes para problemas potencialmente complexos.
Como fazer com que duas ou mais aplicações (potencialmente serviços ou microsserviços) que utilizam os dados de um determinado tipo de entidade, operem de forma eventualmente consistente, com o mínimo de acoplamento, sem sobrecarregar a rede e sem introduzir pontos críticos de falha?
A resposta para a pergunta acima, como não poderia deixar de ser, é um sonoro DEPENDE.
Geralmente, fazer com que todas as aplicações utilizem o mesmo banco de dados não é a melhor escolha. Afinal, essa decisão faria com que todos os sistemas operassem de maneira extremamente acoplada tornando a evolução mais lenta. Além disso, o banco em si se converteria em um ponto crítico de falha. Por outro lado, trata-se da solução com o menor custo de desenvolvimento e parece “OK” em cenários onde o schema está estável e o time de desenvolvimento das aplicações seja o mesmo.
Desenvolver um serviço que opere como “fonte da verdade” para um determinado tipo de entidade, sendo consumido por todos os demais serviços, também não parece ser uma estratégia muito inteligente. Afinal, o acoplamento não seria em função do schema do banco de dados, mas em função do contrato do serviço. Além disso, o serviço também seria um ponto crítico de falhas (sofrendo instabilidades, comprometeria potencialmente o sistema como um todo). De qualquer forma, seria “OK” caso o volume de consumo fosse pequeno.
A melhor estratégia parece ser fazer com que cada serviço mantenha uma cópia dos dados que precisa para funcionar, pelo menos para as operações on-line. Dessa forma, seria necessário mais espaço para armazenamento (o que custa pouco), mas não haveria implicações com instabilidades externas (sem pontos de falha) e não haveria sobrecarga desnecessária na estrutura, principalmente se a frequência de modificação dos dados é pequena. De qualquer forma, trata-se da abordagem com maior complexidade associada e complexidade é custo.
Quando temos dados de uma mesma entidade, replicados em diversas fontes de dados, podemos garantir a consistência (atualização dos dados), mesmo que eventual, através de eventos de notificação, que são lançados toda vez que uma entidade é alterada. Esses eventos “carregariam” os dados atualizados e, sendo “escutados” por todas as aplicações que precisam desses dados, poderiam servir como fonte para a atualização sem que a fonte precise ser consultada.
Essa abordagem é significativamente mais poderosa se os eventos disparados carregassem contexto de modificação (por exemplo: AddressUpdated, SalaryIncreased, etc.). Afinal, nem todos os serviços teriam que manter “todos” os dados das entidades de interesse.
Importante destacar que essa abordagem torna-se bem complexa caso mais de uma aplicação ou serviço opere como interface de modificação para um mesmo subconjunto de dados.
Você já utilizou ou considerou utilizar eventos de notificação para dar consistência de dados em sistemas distribuídos? Já se deparou com o problema indicado nesse post?
Elemar, com cada serviço mantendo uma cópia da entidade, qual a melhor abordagem quando estamos subindo um novo serviço e esse não tem os dados passados?
Para esses casos estou começando a considerar o CDC, change data capture. Umas das formas do cdc seria pegar essas alterações pelo log do banco caso tenha. Mas carece de estudo ainda
Estou usando exatamente esta abordagem, especialmente depois de ouvir um podcast com um caso de sucesso usando microserviços autônomos (guardam dados de outros serviços com base em eventos) que, em suma, têm tudo que precisam para realizar sua atividade.