Nos dias atuais, as empresas de médio/grande porte estão cada vez mais utilizando sistemas distribuídos para garantir que suas aplicações suportem um número crescente de usuários, o que consequentemente resulta em um aumento no número de requisições por segundo. Embora haja diversos aspectos a serem considerados em relação às aplicações distribuídas, gostaria de focar especificamente na questão da consistência em sistemas de banco de dados distribuídos escaláveis.
Existem várias estratégias viáveis para escalar um banco de dados relacional. Uma delas é aumentar os recursos de hardware, como adicionar mais memória, CPU e armazenamento, o que é conhecido como escalonamento vertical (scaling up). Outra estratégia para melhorar a capacidade de processamento em consultas é adicionar réplicas de leitura (read-replicas). Embora essas estratégias sejam amplamente utilizadas, elas também apresentam desafios que podem variar dependendo da aplicação.
Read-Replicas
Na imagem abaixo, podemos observar uma arquitetura básica para a distribuição dos bancos de dados nessa organização, utilizando read-replicas. Você configura um ou mais nós que atuarão como read-replicas, além de um banco de dados principal. O banco de dados principal é conhecido como Primary, enquanto as read-replicas são chamadas de Secondary. Essa terminologia pode variar e também pode ser encontrada como master-slave.
O funcionamento básico consiste em permitir operações de escrita apenas no banco de dados Primary, sendo que todas essas alterações são então replicadas nos bancos secundários. Qualquer operação de leitura, por sua vez, é processada pelas réplicas secundárias. Essa abordagem torna a aplicação mais tolerante a falhas. Entretanto, o tempo de resposta do servidor para o cliente pode ser afetado, dependendo de como essas réplicas estão sendo atualizadas, o que pode ser prejudicial em determinados contextos. É neste ponto que entra em cena a consistência eventual.
O que significa consistência eventual?
Primeiramente, devemos entender o que é consistência. Isso se refere a uma consulta de banco de dados que retorna os mesmos dados sempre que o mesmo pedido é feito.
Na consistência eventual, os resultados são menos consistentes inicialmente, porém são fornecidos muito mais rapidamente, com baixa latência. Os resultados iniciais de consultas de dados com consistência eventual podem não refletir as atualizações mais recentes, pois leva tempo para que as atualizações alcancem réplicas em todo o cluster de banco de dados.
Além disso, existe o conceito de consistência forte, onde significa que os dados mais recentes são retornados. No entanto, devido a métodos internos de consistência, isso pode resultar em maior latência ou atraso.
Vamos analisar o cenário abaixo e entender como ocorre essa consistência eventual dos dados em nosso contidiano.
O usuário adiciona um valor X em uma conta pelo aplicativo. Esse valor é então persistido no banco de dados principal (Primary). Após essa operação, o processo de replicação ocorre rapidamente na réplica 1 (Secondary 1), porém há uma latência maior na réplica 2 (Secondary 2). Quando o usuário verifica o saldo, a consulta pode ser direcionada tanto para a réplica 1 quanto para a réplica 2. No caso mencionado, a consulta foi direcionada para a réplica 2, onde o saldo ainda não havia sido atualizado. Como resultado, o usuário ficou insatisfeito e teve que verificar novamente o saldo para visualizar a atualização correta.
Conclusão
A consistência eventual oferece uma abordagem que prioriza a escalabilidade e a baixa latência, permitindo que as atualizações de dados sejam propagadas de forma assíncrona. No entanto, isso pode resultar em situações onde os dados podem não estar imediatamente consistentes em todas as réplicas, o que requer estratégias adequadas para lidar com essa eventual inconsistência.
Por outro lado, a consistência forte garante que os dados sejam atualizados de forma síncrona em todas as réplicas, garantindo uma visão consistente do estado do sistema. No entanto, isso pode acarretar em maior latência e sobrecarga devido à necessidade de sincronização imediata entre os nós do sistema.
Em última análise, a escolha entre consistência eventual e consistência forte depende das necessidades específicas da aplicação e das prioridades em termos de desempenho, escalabilidade e tolerância a falhas. É crucial entender os requisitos do sistema e as características do ambiente para implementar a estratégia de consistência mais adequada.
Top comments (0)