Como Escalar o Elasticsearch para Resolver Seus Problemas de Escalabilidade

Com a evolução das aplicações modernas atendendo a crescentes necessidades de processamento e recuperação de dados em tempo real, a escalabilidade também se torna importante. Um mecanismo de busca e análise distribuído de código aberto é o Elasticsearch, que é muito eficiente no tratamento de dados em grandes conjuntos e consultas de alta velocidade. No entanto, o processo de dimensionar o Elasticsearch de forma eficaz pode ser sutil, uma vez que é necessário ter um entendimento adequado da arquitetura por trás dele e das compensações de desempenho.

Embora a natureza distribuída do Elasticsearch permita escalonamento horizontal, isso também introduz mais complexidades na forma como os dados são distribuídos e as consultas são atendidas. Um dos desafios teóricos associados ao escalonamento do Elasticsearch é a sua natureza inerentemente distribuída. Na maioria dos cenários práticos, as leituras em um nó independente sempre terão melhor desempenho do que as leituras em um cluster shard. Isso ocorre porque, em um cluster shard, a propriedade dos dados é distribuída entre vários nós. Isso significa que cada consulta pode ter que enviar várias solicitações para diferentes nós, agregar os resultados de volta no nó coordenador e retornar o resultado. Essa sobrecarga de rede adicional facilmente resultará em aumento de latência em comparação com uma arquitetura de um único nó, onde o acesso aos dados é direto.

Nesse sentido, clusters shard são fundamentais para dimensionar o Elasticsearch para grandes conjuntos de dados, alto tráfego e indexação quase em tempo real. Conhecer o equilíbrio entre distribuir os dados entre os nós e manter baixa a latência das consultas é fundamental para alcançar um desempenho ideal. Além disso, o artigo aborda os aspectos teóricos da escalabilidade do Elasticsearch, estratégias práticas de otimização de desempenho do cluster e lições aprendidas com experiências de implantação do mundo real.

No Swoo, nosso aplicativo de streaming ao vivo e jogos, Elasticsearch era a espinha dorsal de todas as coisas relacionadas à busca, e funcionava muito bem à medida que o crescimento de usuários aumentava. No momento em que o número de usuários paralelos ultrapassou 150.000, a página de busca começou a falhar de vez em quando, e ficou bem claro que havia algum gargalo no cluster do 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 busca quanto da página inicial.

Entendendo 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, com cada índice, por sua vez, dividido em shards. O shard é a unidade básica de armazenamento de dados e indexação no Elasticsearch, uma vez que o sistema distribui e paraleliza as operações de busca entre vários nós do cluster.

Um cluster típico conteria um número de nós de dados que hospedam um subconjunto dos dados que executam consultas de busca. Por padrão, o Elasticsearch pode distribuir automaticamente os dados entre os nós, de forma que cada nó executa apenas uma parte da carga de consulta. Dessa forma, o Elasticsearch escala horizontalmente: processa cada vez mais dados e atende cada vez mais requisições simplesmente adicionando nós a ele.

Essa compensação entre escalabilidade e desempenho de consulta é, certamente, uma das coisas mais importantes a se considerar ao projetar clusters do Elasticsearch, especialmente para aplicações que exigem alto rendimento de gravação em combinação com baixa latência de leitura. Esse desafio realmente requer uma configuração cuidadosa do cluster juntamente com uma mistura de técnicas de otimização.

Portanto, essencialmente, nosso cluster do Elasticsearch tinha alguns nós de dados para o caso da Swoo e três nós mestres dedicados. Cada nó rodava 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 latência mínima entre os nós.

Planejando sua Estratégia de Dimensionamento

Em outras palavras, dimensionar o Elasticsearch efetivamente 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 rendimento 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 precisa de atenção ao escalar 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 esteja corretamente dimensionado. De modo geral, escalonamento horizontal (adição de nós ao cluster) é geralmente a melhor abordagem para o aumento do volume de dados e tráfego. No entanto, neste caso, o escalonamento 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% mês a mês, com cada usuário gerando um volume considerável de dados de eventos durante o uso do jogo. Com base nessas projeções, esperávamos ver nosso cluster suportar um aumento saudável em consultas simultâneas junto com um aumento no volume de documentos indexados. Portanto, analisamos se escalar horizontalmente adicionando mais nós de dados ou escalar verticalmente atualizando nossos nós atuais seria mais adequado para esse aumento.

Técnicas de Escalonamento Principais

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 a otimização de ingestão de dados, gerenciamento de shards e otimização do uso de memória.

As principais áreas de foco serão a ingestão de dados. O Elasticsearch suporta nativamente a indexação em massa, 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 mais alto, digamos, 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 a funcionalidade de escalabilidade do Elasticsearch incluem gerenciamento de shard. Embora o Elasticsearch seja capaz de escalar horizontalmente por meio de shard, o dimensionamento de shard inadequado na verdade leva a uma degradação de desempenho. O número de shards sendo muito alto ou muito baixo resulta em velocidade de indexação degradada e/ou desempenho de consulta. O truque está no equilíbrio para um desempenho ótimo no Elasticsearch.

Claro, 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 JVM, configurando o cache de dados de campo e habilitando o cache de consultas. O uso adequado de memória e as configurações de cache apropriadas podem evitar erros de falta de memória e minimizar a sobrecarga de coleta de lixo.

Uma boa quantidade de sobrecarga do Elasticsearch era devido à 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 lote. 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 enorme, 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 o ID do cliente ou a categoria do produto. Isso economiza o Elasticsearch de pesquisar todos os shards; portanto, o tempo e os recursos utilizados são reduzidos.

O ILM, ou Gerenciamento do Ciclo de Vida do Índice, é outro recurso incrível para ajustar o Elasticsearch à medida que seu conjunto de dados envelhece. Você poderá mover dados mais antigos para armazenamento mais lento e mais barato, enquanto mantém os mais relevantes em 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 a escalabilidade do Elasticsearch são considerações de hardware. Conforme seu cluster cresce, você desejará 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 apropriados para operar eficientemente. Unidades SSD ou NVMe melhorarão significativamente o desempenho, especialmente para operações de indexação e pesquisa, que requerem altas velocidades de acesso aos dados.

Uma das lições mais difíceis de aprender foi que atribuir apenas a contagem padrão de shard aos índices mais recentes nos causaria problemas com hot spotting. Também encontramos um ponto ideal onde nenhum shard estava realmente sobrecarregado com a maioria das atualizações em tempo real vindas de nossa plataforma de jogos, redistribuindo índices de gravação intensiva em vários shards menores, ajustando as réplicas adequadamente.

Insights Teóricos 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 chave importante envolve os compromissos de escalabilidade e desempenho de consulta dentro de um sistema distribuído. Em particular, observa-se que, embora os clusters shardados sejam escaláveis horizontalmente, eles aumentam o overhead de consulta porque os resultados de vários nós devem ser combinados. Isso é em contraste com um único nó onde os dados residem na máquina local e as consultas podem ser executadas sem precisar ‘conversar’ com outros nós. Compreender esse compromisso é importante se alguém projetar um cluster Elasticsearch que precisa equilibrar o desempenho com a 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 de shard relevantes 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 diminuir os desafios que surgem 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 está relacionada à alta pressão no heap da 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 alta. Resolvemos isso ajustando a JVM, especialmente 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, escalar o Elasticsearch também não está isento de desafios. Entre os erros comuns que uma pessoa gostaria de evitar estão o dimensionamento inadequado de fragmentos, falta de monitoramento, excesso de dependência de cache e não utilizar o Gerenciamento de Ciclo de Vida de Índice adequado. Isso economiza bastante tempo e recursos se diagnosticado precocemente por meio de ajustes de configuração proativos.

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 fragmentos. As configurações padrão funcionavam bem sob condições de tráfego moderado, mas falhavam sob tráfego de pico. Nossa solução foi em camadas: revisão da alocação de heap, replicação de índice quente e 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 no 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 do seu cluster antes de implantar novas alterações na produção fornecerão escalabilidade sem problemas para um cluster estável a longo prazo.

  • Ajuste fino dos parâmetros da JVM. Definimos Xms e Xmx para 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 congestionamento e escalonamento de réplicas para os índices mais ativos. Isso garantiu que o tráfego de consultas fosse distribuído uniformemente por todo o 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 significativamente a carga no Elasticsearch para solicitações repetitivas sem perder a responsividade 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 da JVM e latências de consulta. Com base nessas métricas, os ajustes finos foram feitos continuamente.

Planos Futuros ou Expansões da Pilha Tecnológica

Além disso, para o crescimento, gostaríamos de explorar o gerenciamento do ciclo de vida de índices quente-morno-frio, 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, antes de impactar a experiência do usuário.

Conclusão

O dimensionamento 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 do particionamento, ele também apresenta vários desafios que precisam ser controlados para obter um desempenho ótimo. A alta escalabilidade e desempenho de um cluster Elasticsearch podem ser garantidos por meio da ingestão adequada de dados, gerenciamento de fragmentos, uso de memória e otimização de consultas.

Enquanto a migração para o Elasticsearch também foi necessária para o Solr em nosso caso, sem dúvida, além de apenas questões puramente técnicas, uma contribuição importante foi dada no entendimento das dificuldades teóricas que estão realmente ocultas em Sistemas Distribuídos. Esse tipo de ajuste cuidadoso e problemas criativos poderiam permitir um crescimento significativo — um cluster Elasticsearch único de vários fornecedores — que deveria receber milhões de consultas por dia, melhorando seu desempenho de consulta com tempos de resposta muito reduzidos. Elementos teóricos e práticos se misturam 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