Quantos shards eu devo ter em meu cluster do Elasticsearch? | Elastic Blog
Engineering

Quantos shards eu devo ter em meu cluster do Elasticsearch?

O Elasticsearch é uma plataforma bastante versátil, que oferece suporte a vários casos de uso, além de proporcionar excelente flexibilidade em torno das estratégias de organização e replicação de dados. Entretanto, essa flexibilidade às vezes dificulta a determinação antecipada de como organizar melhor os dados em índices e shards, principalmente se você for novato no Elastic Stack. Apesar de escolhas inferiores às ideais não necessariamente causarem problemas logo de início, elas têm o potencial de causar falhas de desempenho à medida que aumentam os volumes de dados com o tempo. Quanto mais dados o cluster contiver, mais difícil também ficará a solução do problema, uma vez que por vezes pode ser necessária a reindexação de grandes quantidades de dados.

Quando nos deparamos com usuários que enfrentam problemas de desempenho, não é incomum que isso possa ser rastreado de volta a problemas em torno de como os dados estão indexados e do número de shards no cluster. Isso é particularmente verdadeiro para casos de uso envolvendo multi-tenancy e/ou uso de índices baseados em tempo. Ao discutir essa questão com os usuários, seja pessoalmente, em eventos, encontros ou por meio do nosso fórum, algumas das dúvidas mais comuns são “Quantos shards devo ter?” e “Qual é o tamanho que os shards devem ter?”.

Esta plotagem de blog tem como objetivo ajudar você a responder essas dúvidas e fornecer orientações práticas para casos de uso que envolvem o uso de índices baseados em tempo, por exemplo, análise de logs ou segurança, em um único local.

O que é shard?

Antes de começarmos, precisamos estabelecer alguns fatos e terminologia de que precisaremos em seções mais adiante.

Os dados no Elasticsearch estão organizados em índices. Cada índice consiste em um ou mais shards. Cada shard é uma instância de um índice de Lucene, que pode ser considerado um mecanismo de pesquisa autocontido que indexa e manipula consultas para um subconjunto dos dados em um cluster do Elasticsearch.

À medida que os dados são gravados em um shard, eles são publicados periodicamente em novos segmentos Lucene imutáveis no disco, e é nessa hora que ficam disponíveis para consultas. Isso é denominado atualização. O modo de funcionamento disso é descrito em mais detalhes em Elasticsearch: the Definitive Guide (Guia definitivo do Elasticsearch).

À medida que cresce o número de segmentos, estes são consolidados periodicamente em segmentos maiores. Esse processo é denominado mesclagem. Como todos os segmentos são imutáveis, isso significa que o espaço em disco usado normalmente oscilará durante a indexação, à medida que novos segmentos mesclados precisem ser criados antes que os substituídos possam ser excluídos. A mesclagem pode usar muitos recursos, principalmente com relação a E/S de disco.

O shard é a unidade em que o Elasticsearch distribui dados em torno do cluster. A velocidade em que o Elasticsearch pode mover shards ao rebalancear dados, por exemplo, após uma falha, dependerá do tamanho e número de shards, além do desempenho da rede e do disco.

DICA Evite ter shards muito grandes porque isso pode prejudicar a capacidade de recuperação do cluster após falha. Não há limite fixo sobre o tamanho máximo dos shards, mas um tamanho de 50 GB em geral é citado como limite que parece funcionar para vários casos de uso.

Índice por período de retenção

Como os segmentos são imutáveis, atualizar um documento exige que o Elasticsearch primeiro encontre o documento existente, marque-o como excluído e adicione a versão atualizada. Excluir um documento também exige que o documento seja encontrado e marcado como excluído. Por isso, os documentos excluídos continuarão ocupando espaço em disco e alguns recursos de sistema até que sejam mesclados, o que pode consumir mais recursos do sistema.

O Elasticsearch permite que índices completos sejam excluídos com muito eficiência diretamente do sistema de arquivos, sem explicitamente obrigar a exclusão de todos os registros individualmente. Isso é de longe o jeito mais eficiente de excluir do Elasticsearch.


DICA: Tente usar índices baseados em tempo para gerenciar a retenção de dados sempre que possível. Agrupe os dados em índices com base no período de retenção. Os índices baseados em tempo também tornam fácil variar o número de réplicas e shards primários com o tempo, uma vez que isso pode ser alterado para o próximo índice a ser gerado. Isso simplifica a adaptação a eventuais alterações feitas em volumes de dados e requisitos.


Os índices e shards não são gratuitos?

Para cada índice do Elasticsearch, as informações sobre mapeamentos e estado são armazenadas no estado do cluster. Elas são mantidas na memória para agilizar o acesso. Assim, ter um grande número de índices e shards em um cluster pode resultar em um estado de cluster grande, principalmente se os mapeamentos forem grandes. Isso pode tornar lento o processo de atualização, porque todas as atualizações precisam ser feitas através de um único thread para garantir consistência antes que as alterações sejam distribuídas no cluster.


DICA: Para reduzir o número de índices e evitar mapeamentos grandes e dispersos, avalie armazenar dados com estrutura semelhante no mesmo índice em vez de dividi-los em índices separados com base no local de origem dos dados. É importante encontrar um bom equilíbrio entre o número de índices e shards, e o tamanho do mapeamento para cada índice individual. Como o estado do cluster está carregado no mapa em cada nó (incluindo os mestres), e a quantidade de heap é diretamente proporcional ao número de índices, campos por índice e shards, é importante também monitorar a utilização de heap nos nós mestres e garantir que tenham tamanho apropriado.  


Cada shard tem dados que precisam ser mantidos na memória e usam espaço de heap. Isso inclui estruturas de dados que contêm informações no nível de shard, mas também no nível de segmento para definir onde os dados residem no disco. O tamanho dessas estruturas de dados não é fixo e vai variar dependendo do caso de uso.

Uma característica importante do overhead relacionado ao segmento, entretanto, é que ele não é estritamente proporcional ao tamanho do segmento. Isso significa que segmentos maiores têm menos overhead por volume de dados em comparação com segmentos menores. A diferença pode ser substancial.

Para poder armazenar tantos dados quanto possíveis por nó, torna-se importante gerenciar a utilização de heap e reduzir a quantidade de overhead ao máximo possível. Quanto mais espaço de heap um nó tiver, mais dados e shards ele poderá manipular.

Assim, os índices e shards não são gratuitos do ponto de vista de um cluster, porque há algum nível de overhead de recurso para cada índice e shard.


DICA: Pequenos shards resultam em pequenos segmentos, o que aumenta o overhead. Tenha como objetivo manter o tamanho médio de shard entre pelo menos alguns GB e algumas dezenas de GB. Para casos de uso com dados baseados em tempo, é comum ver shards entre 20 GB e 40 GB de tamanho.

DICA: Como o overhead por shard depende da contagem e tamanho do segmento, obrigar segmentos menores a mesclar para maiores através de uma operação forcemerge pode reduzir o overhead e melhorar o desempenho das consultas. O ideal é que isso seja feito depois que nenhum dado seja gravado no índice. Esteja ciente de que essa é uma operação cara que deve ser executada durante horários fora de pico.

DICA: O número de shards que você pode manter em um nó será proporcional à quantidade de heap disponível, mas não há limite fixo imposto pelo Elasticsearch. Uma ótima regra prática é garantir que você mantenha o número de shards por nó abaixo de 20 GB por heap que ele configurou. Um nó com heap de 30 GB portanto deve ter no máximo 600 shards, mas quanto mais abaixo desse limite você conseguir mantê-lo, melhor será. Isso geralmente ajudará o cluster a ficar com boa integridade.


De que maneira o tamanho do shard influencia no desempenho?

No Elasticsearch, cada consulta é executada em um único thread por shard. Entretanto, vários shards podem ser processados paralelamente, assim como várias consultas e agregações com base no mesmo shard.

Isso significa que a mínima latência de consulta, quando não há cache envolvido, dependerá dos dados, do tipo de consulta e do tamanho do shard. A consulta de muitos pequenos shards tornará o processamento por shard mais rápido, mas como muito mais tarefas precisam ser enfileiradas e processadas em sequência, isso não necessariamente será mais rápido do que consultar um número menor de shards maiores. Ter muitos pequenos shards também pode reduzir o throughput de consulta se houver várias consultas simultâneas.


DICA: A melhor maneira de determinar o tamanho máximo de shard do ponto de vista do desempenho das consultas é adotar um parâmetro de comparação usando dados e consultas realistas. Sempre adote um parâmetro de comparação com uma consulta e um representante de carga de indexação daquilo que o nó precisaria manipular em produção, uma vez que otimizar para uma única consulta pode gerar resultados enganosos.


Como gerencio o tamanho do shard?

Ao usar índices baseados no tempo, cada índice tradicionalmente é associado a um período de tempo fixo. Os índices diários são muito comuns e em geral são usados para manter dados com curto período de retenção ou grandes volumes diários. Isso permite que o período de retenção seja gerenciado com boa granularidade e facilita o ajuste para alterações feitas em volumes diariamente. Dados com um período de retenção mais longo, principalmente se os volumes diários não garantirem o uso de índices diários, em geral usam índices semanais ou mensais para manter grande o tamanho do shard. Isso reduz o tamanho dos índices e shards que precisam ser armazenados no cluster com o tempo.


DICA: Se estiver usando índices baseados no tempo abrangendo um período fixo, ajuste o período que cada índice abrange com base no período de retenção e nos volumes de dados esperados para atingir o tamanho do shard de destino.


Índices baseados no tempo com intervalo de tempo fixo funcionam bem quando os volumes de dados são razoavelmente previsíveis e se alteram lentamente. Se a taxa de indexação puder variar rapidamente, ficará muito difícil manter um tamanho de shard de destino uniforme.

Para poder manipular melhor esse tipo de cenário, as APIs de Rollover e Encolhimento foram introduzidas. Elas adicionam bastante flexibilidade à maneira como os índices e shards são gerenciados, especificamente para índices baseados no tempo.

A API de índice de rollover possibilita especificar o número de documentos que um índice deve conter e/ou o período máximo em que os documentos devem ser gravados nele. Depois que um desses critérios tiver sido excedido, o Elasticsearch poderá disparar um novo índice a ser criado para gravar sem inatividade. Em vez de precisar que cada índice abranja um período de tempo específico, agora é possível trocar para um novo índice com tamanho específico, o que possibilita atingir mais facilmente um tamanho de shard uniforme para todos os índices.

Nos casos em que os dados podem ser atualizados, não há mais um link distinto entre o carimbo de tempo do evento e o índice no qual ele reside ao usar essa API, o que pode tornar as atualizações significativamente menos eficientes porque cada atualização pode precisar ser precedida por uma pesquisa.


DICA: Se você tiver dados imutáveis baseados em tempo em que os volumes podem variar significativamente com o tempo, avalie o uso da API de índice de rollover para atingir um tamanho de shard de destino ideal variando dinamicamente o período de tempo que cada índice abrange. Isso oferece ótima flexibilidade e pode ajudar a evitar a necessidade de ter shards muito grandes ou muito pequenos quando os volumes são imprevisíveis.


A API de encolhimento de índices permite encolher um índice existente para um novo índice com menos shards primários. Se uma dispersão uniforme de shards entre os nós for desejada durante a indexação, mas isso resultará em shards muito pequenos, essa API poderá ser usada para reduzir o número de shards primários depois que houver a indexação. Isso resultará em shards maiores, mais adaptados para armazenamento de dados em períodos mais longos.


DICA: Se você precisar que cada índice abranja um período de tempo específico, mas ainda assim quiser poder dispersar a indexação entre um grande número de nós, avalie o uso da API de encolhimento para reduzir o número de shards primários depois que não houver mais indexação. Essa API também pode ser usada para reduzir o número de shards caso você tenha inicialmente configurado muitos shards.


Conclusões

Esta postagem de blog forneceu dicas e orientações práticas sobre como gerenciar melhor os dados no Elasticsearch. Se tiver interesse em saber mais, a publicação "Elasticsearch: the definitive guide" contém uma seção sobre como projetar para escala, que vale a pena ler apesar de ser um pouco antiga.

Muitas decisões em torno de como distribuir melhor os dados entre índices e shards, entretanto, dependerão de especificidades dos casos de uso, e às vezes poderá ser difícil determinar como aplicar melhor o aviso disponível. Para saber de mais avisos aprofundados e pessoais, participe conosco comercialmente através de uma assinatura e deixe que as equipes de Suporte e Consultoria ajudem a acelerar o projeto. Se estiver satisfeito em discutir seu caso de uso abertamente, você também poderá obter ajuda da nossa comunidade e através do nosso fórum público.