Com a evolução das aplicações modernas atendendo a necessidades crescentes de processamento e recuperação de dados em tempo real, a escalabilidade também cresce. Um mecanismo de busca e análise distribuído e de código aberto é o Elasticsearch, que é muito eficiente no manuseio de dados em grandes conjuntos e consultas de alta velocidade. No entanto, o processo para escalar o Elasticsearch de forma eficaz pode ser sutil, uma vez que é necessário um entendimento adequado da arquitetura por trás dele e dos trade-offs de desempenho.
A natureza distribuída do Elasticsearch permite que ele escale horizontalmente, mas isso também introduz mais complexidades em como os dados são distribuídos e as consultas atendidas. Um dos desafios teóricos associados à escalabilidade do Elasticsearch é sua natureza inerentemente distribuída. Na maioria dos cenários práticos, as leituras em um nó autônomo sempre superarão as leituras em um cluster fragmentado. Isso ocorre porque, em um cluster fragmentado, a propriedade dos dados é espalhada por vários nós. Isso significa que cada consulta pode ter que enviar múltiplas requisições para diferentes nós, agregar os resultados de volta no nó coordenador e retornar o resultado. Essa sobrecarga de rede extra facilmente resultará em maior latência em comparação com uma arquitetura de nó único, onde o acesso aos dados é direto.
Neste aspecto, clusters fragmentados são fundamentais para escalar o Elasticsearch para grandes conjuntos de dados, alto tráfego e indexação quase em tempo real. Conhecer o equilíbrio fino entre espalhar os dados entre os nós e manter a latência das consultas baixa é fundamental para alcançar um desempenho ideal. Mais adiante, o artigo aborda os aspectos teóricos da escalabilidade do Elasticsearch, estratégias práticas de otimização de desempenho de cluster e lições aprendidas com experiências de implantação no mundo real.
Na Swoo, nosso aplicativo de transmissão ao vivo e jogos, o Elasticsearch era a espinha dorsal de todas as pesquisas, e funcionava bem à medida que nosso crescimento de usuários aumentava. No momento em que o número de usuários em paralelo ultrapassou 150.000, a página de pesquisa começou a falhar de vez em quando, e ficou claro que havia algum gargalo no cluster Elasticsearch. Isso logo se tornou inaceitável para um ambiente de jogo ao vivo e nos levou a fazer uma série de otimizações, que finalmente estabilizaram tanto nossas experiências de pesquisa quanto de página inicial.
Compreendendo a Arquitetura do Elasticsearch para Escalabilidade
O Elasticsearch suporta nativamente uma arquitetura distribuída, tornando o sistema altamente escalável, mas, ao mesmo tempo, mais complexo em comparação com soluções tradicionais de nó único. O Elasticsearch divide os dados em índices, sendo que cada índice, por sua vez, é dividido em fragmentos. O fragmento é a unidade básica de armazenamento de dados e indexação no Elasticsearch, já que o sistema distribui e paraleliza as operações de pesquisa em vários nós do cluster.
Um cluster típico conteria vários nós de dados hospedando um subconjunto dos dados que executam consultas de pesquisa. Por padrão, o Elasticsearch pode distribuir automaticamente os dados entre os nós, para que cada nó execute apenas uma parte da carga da consulta. Dessa forma, o Elasticsearch escala horizontalmente: processa cada vez mais dados e atende a cada vez mais solicitações simplesmente adicionando nós a ele.
Essa compensação entre escalabilidade e desempenho de consulta é, naturalmente, uma das coisas mais importantes a considerar ao projetar clusters do Elasticsearch, especialmente para aplicações que exigem alta taxa de gravação combinada com baixa latência de leitura. Esse desafio, de fato, exige uma configuração cuidadosa do cluster juntamente com uma mistura de técnicas de otimização.
Portanto, em essência, nosso cluster do Elasticsearch tinha alguns nós de dados para o caso da Swoo e três nós mestres dedicados. Cada nó funcionava em uma CPU de 8 núcleos com 16 GB de RAM, principalmente voltados para indexação em tempo real e buscas instantâneas dos eventos de jogos em andamento. Como trabalhamos com alta concorrência, precisamos dedicar largura de banda de rede realmente substancial para garantir a latência mínima entre os nós.
Planejando sua Estratégia de Escalonamento
Em outras palavras, escalonar o Elasticsearch de forma eficaz requer análise das métricas de desempenho atuais, identificação de gargalos e definição de metas claras em relação à escalabilidade. Por exemplo, será ótimo monitorar a latência da consulta, o throughput e a saúde do cluster para entender as limitações do seu cluster. Você será capaz de criar um plano de otimização identificando shards quentes, picos de CPU e problemas de memória.
Outra atividade importante que requer atenção ao dimensionar o Elasticsearch é o planejamento de capacidade. Estimar o uso de disco, o padrão de tráfego e os requisitos de retenção de dados garantirá que seu cluster tenha o tamanho correto. Em geral, a escala horizontal (adição de nós ao cluster) é geralmente a melhor abordagem para lidar com o aumento de dados e volume de tráfego. Neste caso, no entanto, a escala vertical – atualização dos recursos de nós individuais – pode ser eficaz.
Nossas projeções indicaram um crescimento de usuários ativos de aproximadamente 10-15% ao mês, sendo que cada usuário gera um volume significativo de dados de evento ao usar o jogo. Com base nessas projeções, esperávamos ver nosso cluster suportar um aumento saudável em consultas simultâneas, juntamente com um aumento no volume de documentos indexados. Portanto, analisamos se a escala horizontal, adicionando mais nós de dados, ou a escala vertical, atualizando nossos nós atuais, seria mais adequada para esse aumento.
Técnicas Principais de Dimensionamento
A otimização do Elasticsearch envolverá uma série de estratégias, cada uma visando diferentes aspectos do sistema. Entre essas, as técnicas mais eficazes incluem otimização de ingestão de dados, gerenciamento de fragmentos e otimização do uso da memória.
As principais áreas de foco serão a ingestão de dados. O Elasticsearch suporta nativamente a indexação em lote, o que significa que você pode enviar lotes muito grandes de documentos em uma única solicitação. Isso reduz a sobrecarga e geralmente acelera o processo de indexação. Em segundo lugar, ajustar o intervalo de atualização pode fazer toda a diferença ao ingerir dados rapidamente. Você pode substituir o intervalo de atualização padrão de um segundo por um valor maior, por exemplo, dez segundos, porque isso reduzirá o estresse de atualizações muito frequentes em seu cluster, e suas gravações serão mais rápidas.
Outros motivos-chave que compõem o recurso de escalabilidade do Elasticsearch incluem gerenciamento de fragmentos. Embora o Elasticsearch seja capaz de escalar horizontalmente por meio de fragmentação, o dimensionamento inadequado dos fragmentos realmente leva a um desempenho degradado. O número de fragmentos sendo muito alto ou muito baixo resulta em velocidade de indexação e/ou desempenho de consulta degradados. O segredo está no equilíbrio para obter um desempenho ideal no Elasticsearch.
É claro que o gerenciamento de memória é outro fator muito importante na escalabilidade do Elasticsearch. Você definitivamente reduz o consumo de recursos e melhora o desempenho de suas consultas otimizando o tamanho do heap do JVM, configurando o cache de dados de campo e habilitando o cache de consultas. O uso adequado de memória e as configurações adequadas de cache podem evitar erros de falta de memória e minimizar a sobrecarga de coleta de lixo.
Uma boa quantidade de sobrecarga do Elasticsearch se devia à ingestão contínua de dados de jogos em tempo real. Otimizamos os pipelines de ingestão por meio do agrupamento de documentos através da API em massa. Em períodos de carga de pico específica, poderíamos aumentar ainda mais o tamanho dos lotes e aumentar o período de atualização para obter um equilíbrio adequado entre a indexação quase em tempo real e a estabilidade geral do cluster.
Soluções Avançadas de Dimensionamento
Quando a escala se torna grande, o Elasticsearch requer técnicas mais avançadas para ser performático. Entre elas, a otimização de consultas se destaca. Você também pode reduzir significativamente a latência da consulta escrevendo consultas eficientes que minimizam o número de shards envolvidos na pesquisa. Por exemplo, você pode fazer roteamento personalizado para direcionar as consultas para os shards específicos usando uma chave, como ID do cliente ou categoria do produto. Isso economiza o Elasticsearch de pesquisar todos os shards; portanto, o tempo e os recursos utilizados são reduzidos.
ILM, ou Gerenciamento de Ciclo de Vida de Índice, é outro recurso incrível para ajustar o Elasticsearch à medida que seus dados envelhecem. Você poderá mover dados mais antigos para um armazenamento mais lento e barato, mantendo os mais relevantes em um armazenamento mais rápido e acessível, dimensionando uma arquitetura quente-morno-frio. Isso mantém o desempenho do cluster excelente à medida que o cluster cresce.
Os tópicos finais de discussão sobre escalabilidade do Elasticsearch são considerações de hardware. À medida que seu cluster cresce, você vai querer garantir que o hardware esteja devidamente provisionado para a carga aumentada. Isso significa garantir que os nós tenham CPU, memória e E/S de disco apropriadas para operar de forma eficiente. Unidades SSD ou NVMe irão melhorar significativamente o desempenho, especialmente para operações de indexação e pesquisa, que requerem altas velocidades de acesso aos dados.
Uma das lições aprendidas com dificuldade foi que atribuir apenas a contagem de fragmentos padrão para índices mais recentes nos causaria problemas com pontos quentes. Também encontramos um ponto ideal onde nenhum fragmento estava realmente sobrecarregado com a maioria das atualizações em tempo real provenientes de nossa plataforma de jogos, redistribuindo índices de gravação intensiva em vários fragmentos menores, ajustando as réplicas conforme necessário.
Percepções Teóricas e Compromissos de Otimização
Além das otimizações práticas acima, existem algumas considerações teóricas interessantes para dimensionar o Elasticsearch. Uma visão fundamental envolve os compromissos entre escalabilidade e desempenho de consulta dentro de um sistema distribuído. Em particular, observa-se que enquanto clusters fragmentados são horizontalmente escaláveis, eles aumentam a sobrecarga de consulta porque os resultados de vários nós precisam ser combinados. Isso contrasta com um único nó onde os dados residem na máquina local e as consultas podem ser executadas sem ter que ‘conversar’ com outros nós. Compreender esse compromisso é importante se alguém projetar um cluster Elasticsearch que precise equilibrar desempenho com escalabilidade.
Outro aspecto mais teórico do dimensionamento do Elasticsearch é o conceito de localidade dos dados. Você pode executar consultas apenas contra o nó local que hospeda os dados do fragmento relevante usando o parâmetro de consulta preference=local
. Isso minimiza a comunicação entre nós e reduz a latência da consulta. Isso pode reduzir os desafios provenientes da replicação de dados e do balanceamento de carga também. O algoritmo de Seleção de Réplica Adaptativa do Elasticsearch tenta otimizar a execução de consultas escolhendo o melhor nó de réplica sob condições atuais. No entanto, isso não necessariamente traz a execução mais eficaz de uma consulta.
A primeira onda de falhas que experimentamos em nosso ambiente diz respeito à alta pressão no heap JVM. Os servidores Elasticsearch inicialmente rodavam com alocações mínimas de heap, resultando em ciclos de coleta de lixo bastante frequentes sob carga de consulta elevada. Resolvemos isso ajustando o JVM, particularmente alinhando o tamanho mínimo e máximo do heap para 8 GB, o que deu ao Elasticsearch espaço suficiente para processar consultas sem sobrecarregar o heap.
Problemas Comuns e Soluções
É claro que escalar o Elasticsearch também não está isento de desafios. Entre os erros comuns que uma pessoa gostaria de evitar estão dimensionamento inadequado de shards, falta de monitoramento, dependência excessiva de cache e não utilização adequada do Gerenciamento de Ciclo de Vida do Índice. Esses problemas podem economizar muito tempo e recursos se diagnosticados precocemente por meio de ajustes proativos de configuração.
Um dos principais problemas foi não ajustar as configurações padrão do Elasticsearch, tanto em relação à alocação de memória quanto ao gerenciamento de shards. Os padrões funcionavam bem em condições de tráfego moderado, mas falharam sob tráfego intenso. Nossa solução foi multilayered: ela revisou a alocação de heap, a replicação de índice quente e o cache de curto prazo para consultas repetidas. No geral, isso evitou falhas repetidas em todo o cluster e reduziu significativamente os tempos limite.
Guia de Implementação do Mundo Real
Escalar o Elasticsearch envolverá planejamento, testes, implantação e manutenção posterior. Segue-se que boas práticas, modelos de configuração e testes intensivos de seu cluster antes de implementar novas alterações na produção proporcionarão escalabilidade sem problemas em um cluster estável a longo prazo.
- Ajuste fino dos parâmetros do JVM. Definimos tanto o Xms quanto o Xmx como 8 GB em cada servidor Elasticsearch, encontrando um equilíbrio entre a memória do sistema disponível e os requisitos de heap.
- Otimização da distribuição de shards. Índices grandes foram divididos em shards de tamanho menor para evitar pontos de sobrecarga e dimensionamento de réplicas para os índices mais ativos. Isso garantiu que o tráfego de consultas fosse uniformemente distribuído pelo cluster.
- Ativar cache com TTL curto. Aplicamos uma janela de cache de 1 segundo em consultas estáticas frequentemente usadas na página inicial e notamos que isso reduz consideravelmente a carga no Elasticsearch para solicitações repetitivas sem perder a capacidade de resposta em tempo real.
- Monitoramento e iteração. Utilizamos o Kibana, com alguns painéis personalizados para observação em tempo real da saúde dos shards, desempenho do JVM e latências de consulta. Com base nesses métricas, foram feitos ajustes contínuos.
Planos Futuros ou Expansões da Pilha Tecnológica
Além disso, para o crescimento, gostaríamos de explorar a gestão de um ciclo de vida do índice hot-warm-cold movendo dados menos acessados com frequência para nós mais baratos, mantendo hardware de primeira linha para indexação e consultas em tempo real. Estamos considerando soluções avançadas de monitoramento e detecção de anomalias impulsionadas por IA para garantir que picos ou desacelerações em consultas incomuns sejam identificados com antecedência, evitando impactos na experiência do usuário.
Conclusão
A escalabilidade do Elasticsearch requer compreensão da arquitetura, planejamento cuidadoso e implementação das melhores práticas. Por mais que o Elasticsearch escale horizontalmente por meio de shardings, ele apresenta vários desafios que devem ser controlados para um desempenho ideal. A alta escalabilidade e desempenho de um cluster Elasticsearch podem ser garantidos por meio de uma ingestão de dados adequada, gerenciamento de shards, uso de memória e otimização de consultas.
Enquanto a migração para o Elasticsearch foi necessária para o Solr em nosso caso também, sem dúvida, além de apenas questões puramente técnicas, uma contribuição importante foi dada em relação à compreensão das dificuldades teóricas que estão realmente ocultas em Sistemas Distribuídos. Esse tipo de ajuste cauteloso e resolução criativa de problemas poderia permitir um crescimento significativo – um cluster Elasticsearch único de vários fornecedores – que deveria receber milhões de consultas por dia, melhorando o desempenho das consultas em tempos de resposta muito reduzidos. Elementos teóricos e práticos se combinam ao escalar a implantação do Elasticsearch para garantir o sucesso a longo prazo.
Source:
https://dzone.com/articles/how-to-scale-elasticsearch-to-solve-scalability-issues