Dimensionamento Ideal de Fragmentos: Equilibrando Desempenho e Gerenciamento do Cluster

Domine o dimensionamento de fragmentos do Elasticsearch para otimizar o desempenho do cluster. Este guia explora as compensações entre o número e o tamanho dos fragmentos, abordando considerações importantes como volume de dados, carga de indexação e padrões de consulta. Aprenda as melhores práticas para calcular a alocação ideal de fragmentos, aproveitar índices baseados em tempo e implementar o Gerenciamento do Ciclo de Vida de Índices (ILM) para construir um cluster Elasticsearch escalável e eficiente.

Dimensionamento Ideal de Fragmentos: Equilibrando Desempenho e Gerenciamento do Cluster

O dimensionamento de fragmentos é uma daquelas decisões do Elasticsearch que parece simples até o cluster existir por alguns meses. Um fragmento é apenas um índice Lucene internamente, mas cada fragmento tem sobrecarga. Muitos fragmentos pequenos deixam o cluster ocupado gerenciando metadados e alvos de busca minúsculos. Poucos fragmentos grandes tornam a realocação, recuperação e algumas buscas dolorosamente lentas.

Não existe um tamanho de fragmento universal que funcione para todos os clusters. Um cluster de logs com rotação diária, um índice de busca de produtos e um cluster de análise de segurança se comportam de forma diferente. A abordagem útil é escolher um tamanho de fragmento alvo, projetar a rotação ou criação de índice em torno dele e, em seguida, ajustar com base no comportamento real de indexação e consulta.

Fundamentos dos Fragmentos do Elasticsearch

Antes de mergulhar nas estratégias de dimensionamento, é essencial entender os conceitos básicos:

  • Índice: Uma coleção de documentos. No Elasticsearch, um índice é dividido em vários fragmentos.
  • Fragmento: Uma unidade de distribuição. Cada fragmento é um índice Lucene independente. Um índice pode conter vários fragmentos, distribuídos em diferentes nós do cluster.
  • Fragmento Primário: Quando um índice é criado, ele recebe um número de fragmentos primários. Esses fragmentos são onde seus dados são indexados. Você não pode simplesmente editar number_of_shards em um índice existente, mas o Elasticsearch fornece operações de divisão e redução em condições específicas. Muitas equipes ainda tratam o número de fragmentos primários como uma decisão de design, pois alterá-lo posteriormente requer planejamento.
  • Fragmento Réplica: Cópias dos seus fragmentos primários. Eles fornecem redundância e aumentam a taxa de transferência de leitura. Se um fragmento primário falhar, uma réplica pode ser promovida a primário. O número de fragmentos réplica pode ser alterado a qualquer momento.

Como os Fragmentos Impactam o Desempenho

  • Desempenho de Indexação: Cada fragmento requer recursos para indexação. Mais fragmentos significam mais sobrecarga para os nós coordenadores que gerenciam as solicitações. No entanto, se os fragmentos se tornarem muito grandes, a indexação em um único fragmento pode se tornar um gargalo.
  • Desempenho de Consulta: As solicitações de pesquisa são distribuídas para todos os fragmentos primários relevantes. Um número maior de fragmentos pode aumentar o número de solicitações que precisam ser processadas, potencialmente aumentando a latência. Por outro lado, fragmentos muito grandes podem levar a tempos de busca mais longos, pois o Lucene precisa processar mais dados dentro desse fragmento.
  • Gerenciamento do Cluster: Um grande número de fragmentos aumenta a carga no nó mestre, responsável pelo gerenciamento do estado do cluster. Também impacta a sobrecarga de operações como realocação de fragmentos, criação de snapshots e recuperação.
  • Utilização de Recursos: Cada fragmento consome memória e E/S de disco. Muitos fragmentos podem esgotar os recursos do nó, levando à degradação do desempenho ou instabilidade do nó.

Considerações Principais para o Dimensionamento de Fragmentos

O tamanho "ideal" do fragmento não é um número fixo; depende da sua carga de trabalho específica, características dos dados e hardware. No entanto, vários fatores devem orientar suas decisões:

1. Volume de Dados e Taxa de Crescimento

  • Tamanho Atual dos Dados: Quantos dados você tem no seu índice agora?
  • Taxa de Crescimento: Quão rápido seus dados estão crescendo? Isso ajuda a prever tamanhos futuros de fragmentos.
  • Política de Retenção de Dados: Você excluirá dados antigos? Isso impacta o tamanho efetivo dos dados ativos.

2. Carga de Indexação

  • Taxa de Indexação: Quantos documentos por segundo você está indexando?
  • Tamanho do Documento: Qual é o tamanho médio dos documentos individuais?
  • Taxa de Transferência de Indexação: Seus nós conseguem lidar com a carga de indexação com a configuração atual de fragmentos?

3. Padrões de Consulta

  • Complexidade da Consulta: Suas consultas são simples pesquisas por palavras-chave ou agregações complexas?
  • Frequência de Consulta: Com que frequência as consultas são executadas em seus dados?
  • Requisitos de Latência de Consulta: Quais são os tempos de resposta aceitáveis?

4. Topologia e Recursos do Cluster

  • Número de Nós: Quantos nós existem no seu cluster?
  • Hardware do Nó: CPU, RAM e disco (SSD é altamente recomendado para Elasticsearch).
  • Limites de Fragmentos: O Elasticsearch inclui limites de segurança que impedem que um nó mantenha um número excessivo de fragmentos abertos. Versões recentes comumente usam cluster.max_shards_per_node como a proteção em todo o cluster para índices abertos normais. cluster.routing.allocation.total_shards_per_node é diferente: limita quantos fragmentos de um único índice, ou escopo de alocação correspondente, podem ser alocados a um nó. Verifique sua versão do Elasticsearch antes de alterar qualquer uma das configurações.

Melhores Práticas para Alocação de Fragmentos

1. Mire em um Tamanho de Fragmento Alvo

Embora não exista um número mágico, muitos clusters de produção visam fragmentos em torno de 10GB a 50GB para cargas de trabalho comuns de log e pesquisa. Esse intervalo é um ponto de partida, não uma regra. Sistemas de alto rendimento ou retenção longa podem escolher fragmentos maiores após testes; índices de pesquisa de pequenas empresas podem funcionar melhor com um único fragmento pequeno.

  • Muito pequeno (< 10GB): Pode levar a sobrecarga excessiva. Cada fragmento tem uma pegada de memória e contribui para a carga do nó mestre. Gerenciar milhares de fragmentos minúsculos torna-se um fardo operacional significativo.
  • Muito grande (> 50GB): Pode causar problemas de desempenho. A mesclagem de segmentos, recuperação e operações de rebalanceamento demoram mais. Se um fragmento grande falhar, pode levar um tempo considerável para se recuperar.

2. Considere Índices Baseados em Tempo

Para dados de séries temporais (logs, métricas, eventos), usar índices baseados em tempo é uma prática padrão e altamente eficaz. Isso envolve a criação de novos índices para períodos de tempo específicos (por exemplo, diário, semanal, mensal).

  • Exemplo: Em vez de um índice massivo, você pode ter logs-2023.10.26, logs-2023.10.27, etc.
  • Benefícios: Gerenciamento de dados mais fácil (exclusão de índices antigos via Gerenciamento do Ciclo de Vida de Índices - ILM), melhor desempenho, pois as consultas geralmente visam dados recentes, e tamanhos de fragmentos controlados.

3. Implemente o Gerenciamento do Ciclo de Vida de Índices (ILM)

As políticas de ILM permitem automatizar o gerenciamento de índices com base na idade, tamanho ou contagem de documentos. Você pode definir fases para um índice (hot, warm, cold, delete) e especificar ações para cada fase, incluindo alterar o número de réplicas, reduzir índices ou excluí-los.

  • Fase Hot: O índice está sendo ativamente escrito e consultado. Maximize o desempenho.
  • Fase Warm: O índice não é mais escrito, mas ainda é consultado. Pode ser movido para hardware menos potente, potencialmente com menos réplicas ou reduzido.
  • Fase Cold: Consultas pouco frequentes. Os dados podem ser movidos para armazenamento mais barato ou nós de baixo desempenho, dependendo da sua licença, versão e arquitetura do Elasticsearch.
  • Fase Delete: Os dados não são mais necessários e são excluídos.

4. Evite o Excesso de Fragmentação

O excesso de fragmentação ocorre quando você tem muitos fragmentos para o tamanho do seu cluster e volume de dados. Esta é uma armadilha comum que leva a problemas de desempenho e gerenciamento.

  • Sintomas: Alto uso de CPU nos nós mestres, atualizações lentas do estado do cluster, longos tempos de recuperação e lentidão geral.
  • Mitigação: Planeje o número de fragmentos primários desde o início. Para índices baseados em tempo, comece com um número razoável de fragmentos primários por índice (por exemplo, 1 ou 3). Você sempre pode adicionar réplicas depois.

5. Não Crie Índices em Excesso

Da mesma forma, evite criar um número excessivo de índices quando não for necessário. Cada índice adiciona sobrecarga. Para dados que não são de séries temporais e onde você não tem um mecanismo de particionamento natural, considere se um único índice com contagem apropriada de fragmentos é suficiente.

6. Considere a Configuração number_of_shards

Ao criar um índice, o parâmetro number_of_shards define o número de fragmentos primários. Esta configuração é imutável após a criação do índice.

PUT meu-indice
{
  "settings": {
    "index": {
      "number_of_shards": 3,  // Exemplo: 3 fragmentos primários
      "number_of_replicas": 1   // Exemplo: 1 fragmento réplica
    }
  }
}
  • Dica: Para índices menores ou com carga de indexação/consulta muito baixa, um único fragmento primário pode ser suficiente. Para índices maiores e mais ativos, 3 ou 5 fragmentos primários podem oferecer melhor distribuição e resiliência, especialmente se você planeja dividir o índice posteriormente (embora a divisão seja complexa).

7. Rebalanceamento e Realocação

O Elasticsearch rebalanceia automaticamente os fragmentos para garantir uma distribuição uniforme entre os nós. No entanto, se os fragmentos forem muito grandes, essas operações podem consumir muitos recursos e ser lentas. Fragmentos menores e mais numerosos podem, às vezes, rebalancear mais rápido, mas isso é contrabalançado pela sobrecarga de gerenciar mais fragmentos.

8. Ajuste de Desempenho de Consulta

Se o desempenho da sua consulta estiver sofrendo, avalie sua estratégia de fragmentos. Considere:

  • Número de Fragmentos: Muitos fragmentos podem aumentar a sobrecarga de coordenação.
  • Tamanho do Fragmento: Fragmentos muito grandes podem desacelerar a mesclagem de segmentos e a pesquisa dentro do fragmento.
  • Design do Índice: Você está usando mapeamentos e analisadores apropriados?

Calculando o Número Ideal de Fragmentos

Não existe uma fórmula única, mas aqui está uma abordagem comum:

  1. Estime o volume total de dados por índice ao longo de seu ciclo de vida.
  2. Determine o tamanho alvo do fragmento (por exemplo, 30GB).
  3. Calcule o número de fragmentos primários necessários: Volume Total de Dados / Tamanho Alvo do Fragmento.
  4. Arredonde para cima para o número inteiro mais próximo. Isso fornece o number_of_shards para o índice.
    • Exemplo: Se você espera 90GB de dados e visa fragmentos de 30GB, precisaria de 90GB / 30GB = 3 fragmentos primários.
  5. Considere resiliência e distribuição: Para índices críticos, considere usar 3 ou 5 fragmentos primários para permitir melhor distribuição e opções de recuperação, mesmo que seu volume inicial de dados não exija estritamente isso. A compensação é o aumento da sobrecarga.
  6. Comece de forma conservadora: Geralmente é mais fácil adicionar réplicas do que alterar o número de fragmentos primários (o que geralmente requer reindexação ou soluções complexas). Se não tiver certeza, comece com menos fragmentos primários e monitore o desempenho.

Cenário de Exemplo: Análise de Logs

Digamos que você esteja indexando logs de aplicação:

  • Volume de Dados: Você espera 1TB de logs por mês.

  • Retenção de Dados: Você mantém logs por 30 dias.

  • Tamanho Alvo do Fragmento: Você visa 20GB.

  • Índices Diários: Você cria índices diários (logstash-YYYY.MM.DD). Cada índice diário conterá aproximadamente 1TB / 30 dias ≈ 33GB de dados.

  • Fragmentos Primários por Índice: Dado o alvo de 20GB e o volume diário de 33GB, você pode escolher 2 fragmentos primários por índice (33GB / 20GB ≈ 1,65, arredondado para 2). Isso garante que fragmentos individuais permaneçam dentro do tamanho alvo.

  • Réplicas: Você decide 1 réplica para alta disponibilidade.

  • Total de Fragmentos: Ao longo do período de retenção de 30 dias, você terá 30 índices, cada um com 2 fragmentos primários e 2 réplicas, totalizando 60 fragmentos primários e 60 réplicas ativos a qualquer momento.

Essa abordagem mantém fragmentos individuais gerenciáveis e permite a exclusão eficiente de dados simplesmente excluindo índices antigos.

O Que Geralmente Dá Errado

O problema mais comum é o excesso de fragmentação por hábito. Alguém cria índices diários com cinco primários e uma réplica porque um tutorial antigo usava essa configuração. Parece inofensivo no início. Então o cluster tem centenas de índices pequenos, milhares de fragmentos minúsculos e nós mestres gastando muito tempo em atualizações de estado do cluster. As pesquisas também se espalham por muitos fragmentos, o que adiciona sobrecarga de coordenação antes mesmo do trabalho de consulta real começar.

O problema oposto aparece durante a recuperação. Alguns fragmentos enormes podem consultar de forma aceitável em um dia normal, mas quando um nó falha ou uma reinicialização contínua começa, a realocação leva muito tempo. Snapshots e restaurações também podem se tornar mais lentos porque cada fragmento é uma grande unidade de trabalho. Se seu objetivo de recuperação for apertado, o tamanho do fragmento importa mesmo quando a latência da consulta parece boa.

Fragmentos quentes são outro problema prático. Se todas as novas gravações vão para um fragmento primário, adicionar mais nós não distribuirá automaticamente essa carga de gravação. A rotação baseada em tempo ajuda porque novos índices podem ser dimensionados para o padrão de tráfego atual. As escolhas de roteamento também importam. O roteamento personalizado pode ser poderoso, mas uma chave de roteamento ruim pode enviar muitos dados para um fragmento.

Um Padrão de Rotação Melhor

Para dados de séries temporais, a rotação baseada em tamanho é frequentemente mais fácil de gerenciar do que índices diários fixos. Em vez de criar um índice por dia, não importa o que aconteça, você cria um alias de gravação e deixa o ILM fazer a rotação quando o índice atingir um tamanho alvo, idade ou contagem de documentos.

PUT _ilm/policy/logs-policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_primary_shard_size": "30gb",
            "max_age": "1d"
          }
        }
      },
      "delete": {
        "min_age": "30d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

Com esse padrão, um fim de semana tranquilo pode produzir menos índices, enquanto um dia movimentado de incidentes pode fazer a rotação mais cedo. Você ainda precisa escolher o número inicial de primários, mas a rotação impede que o crescimento do fragmento se afaste muito do alvo.

Como Inspecionar Seus Fragmentos Atuais

Antes de mudar qualquer coisa, observe o cluster que você tem:

GET _cat/shards?v&h=index,shard,prirep,state,docs,store,node&s=store:desc
GET _cat/indices?v&h=index,pri,rep,docs.count,store.size,pri.store.size&s=pri.store.size:desc
GET _cluster/health

Você está procurando padrões: muitos fragmentos minúsculos, alguns fragmentos enormes, fragmentos não atribuídos, colocação desigual de nós ou índices cujo tamanho de armazenamento primário está longe do seu alvo pretendido. Se um índice tem 100GB de dados primários e cinco fragmentos primários, cada primário tem aproximadamente 20GB antes das réplicas. Se o mesmo índice tem 100GB e 50 primários, você provavelmente criou sobrecarga desnecessária.

Notas Finais

Um bom dimensionamento de fragmentos tem menos a ver com perseguir um número perfeito e mais com manter o cluster fácil de operar. Comece com um alvo razoável, use ILM ou rotação onde o padrão de dados se encaixa e observe o que realmente acontece com o tamanho do fragmento, a dispersão de consultas, o tempo de recuperação e a pressão no nó. Se o seu cluster já está com excesso de fragmentação, corrija-o gradualmente com novos modelos de índice, rotação, redução ou reindexação, em vez de tentar forçar todos os índices antigos a uma nova forma de uma só vez.