Escalabilidade: conceitos chaves e princípios pra uma entrevista de System design
A escalabilidade é uma das características mais importantes a se considerar no System Design. Em linhas gerais, é a capacidade de um sistema de lidar com um aumento na demanda de forma eficiente, sem prejudicar o desempenho ou a disponibilidade. Esses são os principais pontos a se considerar ao projetar sistemas escaláveis.
Arquitetura horizontal
Também conhecida como “escala pra fora”, é um abordagem bem comum que consiste em adicionar mais nós ao sistema, ao invés de aumentar a capacidade de cada nó individual.
Por exemplo:
Imagina que você precisa lidar com concorrência de usuários em uma aplicação, não é necessário ter uma máquina mega robusta pra aguentar a carga, você pode só adicionar mais instâncias, clones do mesmo servidor de serviço lado a lado. Isso permite que o sistema lide com uma demanda crescente, distribuindo a carga pra mais nós. Você pode distribuir essas solicitações com um balanceador de carga.
Arquitetura vertical
Nesse modelo nós adicionamos mais recursos a uma única máquina como CPU, memória ou melhorar o desempenho do disco. Esse tipo de arquitetura é cara e um pouco perigoso pelo simple fato de não ser tolerante a falhas, pois, se o servidor ficar indisponível, todos o sistema ficará comprometido e fora do ar.
Particionamento
Essa é outra técnica comum para escalabilidade. Basicamente, consiste em dividir o sitema em partes menores de gerenciáveis. Alguns exemplos incluem o particionamento de banco de dados ou a divisão de uma aplicação em microserviços. Mas podemos separar esse conceito em vários exemplos, como:
Particionamento por função: nesse caso, as partições são criadas com base nas funcionalidades dos sistemas. Um bom exemplo seria uma aplicação de rede social onde você pode ter feed de notícias, timeline, chat, etc. Cada função pode ser gerenciada por uma equipe separada, o que ajuda a aumentar a escalabilidade e a eficiência de manutenção.
Particionamento por objeto: essa abordagem consiste em dividir em partições baseadas em objetos do sistema, como produtos, categorias, etc. Cada partição é gerenciada por um servidor separado, um exemplo seria um sistema de banco de dados, que pode ser separado por tabelas, índices, arquivos de logs e etc.
Particionamento por região geográfica: Neste tipo de particionamento, os dados são divididos em partições com base na localização geográfica dos usuários, permitindo que os servidores mais próximos dos usuários possam gerenciar suas solicitações com maior eficiência. Além disso, ajuda a aumentar a disponibilidade, pois os usuários sempre terão acesso ao sistema, mesmo que haja uma interrupção em um dos servidores.
Como exemplo nós temos os aplicativos de transporte como Uber, para garantir que as solicitações de corrida sejam processadas de maneira rápida e eficiente. Por exemplo, o aplicativo pode ter servidores em Nova York, Londres e São Paulo, cada um responsável por atender aos usuários da respectiva região.
Redundância
Redundância é uma estratégia comum usada para aumentar a escalabilidade e disponibilidade dos sistemas pois permite que o sistema continue funcionanando mesmo se as partes falharem. Por exemplo, você pode ter:
Redundância de nós onde vários nós executam a mesma tarefa, de forma que, se um nó falhar, outro possa substituí-lo sem afetar o sistema.
Redundância de dados: cópias dos dados são mantidas em múltiplos locais para garantir que, se um sistema falhar, os dados ainda estarão disponíveis em outro local.
Cache
Acho que cache pode ter um artigo a parte, porque podemos falar de bastante coisa, mas basicamente, cache é uma técnica importante que consiste em armazenar dados frequentes em locais de acesso rápido, como memória, ao invés de ir busca-lo em uma fonte externa toda vez que for requisitado. Isso ajuda a reduzir a sobrecarga em um sistema com uma demanda elevada.
Veja mais sobre cache nesse artigo. — em breve
Teorema de CAP
O Teorema de CAP é uma teoria importante no design de sistemas escaláveis. Ele afirma que é impossível para um sistema distribuído atender simultaneamente aos três critérios de Consistência, Disponibilidade e Latência consistentemente. Portanto, é importante escolher quais critérios são mais importantes para o sistema e projetá-lo de acordo.
Veja mais sobre Teorema de CAP nesse artigo. — em breve
Disponibilidade
É a medida da capacidade de um sistema de estar disponível para atender às solicitações de usuários. É uma parte crítica da escalabilidade, pois permite que o sistema atenda à demanda crescente sem prejudicar a disponibilidade.
Load balancing
O balanceamento de carga é uma técnica importante para garantir a escalabilidade, ele consiste em distribuir a carga entre vários nós, o que permite que o sistema lidem com a demanda crescente sem prejudicar o desempenho.
Veja mais sobre Load Balancer nesse artigo. — em breve
Latência
Latência é a medida do tempo que leva para que uma solicitação seja processada e uma resposta seja retornada. É importante para a escalabilidade, pois um aumento na latência pode prejudicar a experiência do usuário.
Throughput
O throughput é a medida da capacidade de um sistema de processar solicitações em um período de tempo. É importante para a escalabilidade, pois um aumento na demanda pode exigir uma capacidade de processamento maior para atender às solicitações de forma eficiente.
Na hora de escalar um sistema temos que levar em conta alguns trade-offs:
- Consistência vs Disponibilidade: Escolher entre garantir a consistência dos dados ou a disponibilidade do sistema é um trade-off comum. Por exemplo, um sistema que usa replicação de dados pode garantir a consistência, mas pode comprometer a disponibilidade se uma réplica falhar. Por outro lado, um sistema que usa tolerância a falhas pode garantir a disponibilidade, mas pode comprometer a consistência se as réplicas ficarem desatualizadas.
- Latência vs Escalabilidade: Escolher entre reduzir a latência e aumentar a escalabilidade também é um trade-off. Por exemplo, usar cache pode reduzir a latência, mas pode dificultar a escalabilidade se a capacidade do cache for excedida.
- Complexidade vs Escalabilidade: Adotar soluções complexas para garantir a escalabilidade pode ser contraproducente, já que a complexidade pode prejudicar a manutenibilidade e a escalabilidade a longo prazo. Por exemplo, usar um sistema de mensagens complexo pode garantir a escalabilidade, mas pode aumentar a complexidade do sistema e dificultar a manutenção.
- Custo vs Escalabilidade: Adotar soluções caras para garantir a escalabilidade pode ser contraproducente se o custo exceder o benefício. Por exemplo, usar servidores dedicados de alta performance pode garantir a escalabilidade, mas pode ser caro se a demanda não justificar o custo.
Em resumo, escalabilidade é uma questão crítica ao projetar sistemas, uma combinação de arquitetura horizontal, particionamento, redundância, cache e automação pode ajudar a garantir que um sistema possa lidar com demanda crescente sem prejudicar o desempenho.
Perguntas frequentes em uma entrevista de system design
Em uma entrevista de system design sobre escalabilidade, você pode ser questionado sobre as seguintes questões:
Como você planejaria para escalabilidade horizontal e vertical em seu sistema?
Como você garantiria alta disponibilidade em seu sistema?
Como você lidaria com cenários de picos de tráfego em seu sistema?
Como você implementaria load balancing em seu sistema?
Como você garantiria a consistência dos dados em seu sistema?
Como você lidaria com a latência em seu sistema?
Como você melhoraria o throughput em seu sistema?
Como você implementaria o particionamento em seu sistema?
Como você garantiria redundância em seu sistema?
Como você implementaria cache para melhorar o desempenho?