Como gerenciar e solucionar problemas de memória do Elasticsearch
.jpg)
Com o Elastic Cloud oferecendo soluções como Observability, Security, e busca, ampliamos o número de usuários que utilizam o Elastic Cloud além das equipes completas de operações, incluindo engenheiros de dados, equipes de segurança e consultores. Como representante de suporte da Elastic, gostei de interagir com uma ampla variedade de usuários e casos de uso.
Com um público maior, estou vendo mais perguntas sobre como gerenciar a alocação de recursos, em particular solucionar problemas de integridade da alocação e evitar disjuntores. Eu entendo! Quando comecei com o Elasticsearch, eu tinha as mesmas perguntas. Foi minha primeira introdução ao gerenciamento de heap Java e shards de banco de dados de séries temporais e ao redimensionamento de minha própria infraestrutura.
Quando entrei na Elastic, adorei que, além da documentação, tínhamos blogs e tutoriais para que eu pudesse me integrar rapidamente. Mas eu sofri no primeiro mês para correlacionar meu conhecimento teórico com os erros que os usuários enviavam pela minha fila de tíquetes. Por fim, descobri, como outros representantes de suporte, que muitos dos erros relatados eram apenas sintomas de problemas de alocação e que os mesmos sete links ajudariam os usuários a gerenciar sua alocação de recursos com sucesso.
Falando como representante de suporte, vou examinar os principais links da teoria de gerenciamento de alocação que enviamos aos usuários, os principais sintomas que vemos e para onde direcionamos os usuários a atualizar suas configurações para resolver seus problemas de alocação de recursos.
Teoria
Como uma aplicação Java, o Elasticsearch requer uma certa alocação de memória lógica (heap) da memória física do sistema. Essa alocação deve ser de até metade da RAM física, com um limite máximo de 32 GB. Um uso maior do heap geralmente é em resposta a consultas complexas e maior capacidade de armazenamento de dados. O limite de alocação de recursos (circuit breaker) padrão é de 95%, mas recomendamos o redimensionamento de recursos quando esse limite atingir consistentemente 85%.
Eu recomendo muito estes artigos de visão geral para obter mais informações:
Configuração
Prontas para usar, as configurações padrão do Elasticsearch dimensionam automaticamente seu heap da JVM com base na função do nó e na memória total. No entanto, conforme necessário, você pode configurá-lo diretamente das três maneiras a seguir:
1. Diretamente no config > jvm.options dos seus arquivos locais do Elasticsearch:
## JVM configuration
################################################################
## IMPORTANT: JVM heap size
################################################################
…
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
-Xms4g
-Xmx4g2. Como variável do ambiente Elasticsearch no seu docker-compose:
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.0
environment:
- node.name=es01
- cluster.name=es
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms4g -Xmx4g"
- discovery.type=single-node
ulimits:
memlock:
soft: -1
hard: -1
ports:
- 9200:92003. Via nosso Elastic Cloud Hosted > Implantação > Editar visualização. Nota: o menu suspenso atribui memória física e aproximadamente metade será alocada para o heap.

Solução de problemas
Se você está enfrentando problemas de desempenho com seu cluster, provavelmente trata-se dos suspeitos de sempre:
- Problemas de configuração: nós master subdimensionados, sem políticas ILM
- Volume induzido: alta velocidade e carga de solicitações, sobreposição de consultas/escritas custosas
Saúde da alocação
Índices de dados armazenados em sub-shards, que usam o heap para manutenção e durante requisições de busca e escrita. O tamanho do shard não deve ser maior que 50GB. Pegando o exemplo acima do Elastic Cloud Hosted com 8GB de memória física em duas zonas (que alocarão dois nós no total), vamos juntar isso a um exemplo: _cat/allocation.
GET /_cat/allocation?v=true&h=shards,node
shards node
41 instance-0000000001
41 instance-0000000000E para: _cluster/health.
GET /_cluster/health?filter_path=status,*_shards
{
"status": "green",
"unassigned_shards": 0,
"initializing_shards": 0,
"active_primary_shards": 41,
"relocating_shards": 0,
"active_shards": 82,
"delayed_unassigned_shards": 0
}Se algum shard relatar >0 fora de active_shards ou active_primary_shards, você identificou uma causa de problemas de desempenho.
Na maioria das vezes, se isso reportar um problema, será unassigned_shards>0. Se esses shards forem primários, seu cluster reportará como status:red, e se for apenas réplica, reportará como status:yellow. (é por isso configurar réplicas nos índices é importante — se o cluster encontrar um problema, ele pode se recuperar em vez de sofrer perda de dados.) Vamos supor que temos um status:yellow com um único shard não atribuído. Para investigar, daríamos uma olhada em qual shard de índice está tendo problemas via _cat/shards.
GET _cat/shards?v=true&s=state
index shard prirep state docs store ip node
logs 0 p STARTED 2 10.1kb 10.42.255.40 instance-0000000001
logs 0 r UNASSIGNED
kibana_sample_data_logs 0 p STARTED 14074 10.6mb 10.42.255.40 instance-0000000001
.kibana_1 0 p STARTED 2261 3.8mb 10.42.255.40 instance-0000000001Então, isso será para nossos logs de índice que não são do sistema, que têm um shard de réplica não atribuído. Vamos ver o que está causando problemas executando _cluster/allocation/explain. (Dica profissional: quando você encaminha o suporte, é exatamente isso que fazemos.)
GET _cluster/allocation/explain?pretty&filter_path=index,node_allocation_decisions.node_name,node_allocation_decisions.deciders.*
{ "index": "logs",
"node_allocation_decisions": [{
"node_name": "instance-0000000005",
"deciders": [{
"decider": "data_tier",
"decision": "NO",
"explanation": "node does not match any index setting [index.routing.allocation.include._tier] tier filters [data_hot]"
}]}]}Essa mensagem de erro aponta para data_hot, que faz parte de uma política de gestão de ciclo de vida do índice (ILM) e indica que nossa política de ILM é incongruente com as configurações atuais do índice. Nesse caso, a causa desse erro é a configuração de uma política ILM hot-warm sem ter nós quentes designados. (Eu precisava garantir que algo falharia, então estou forçando exemplos de erro para vocês. Para mais informações, veja este vídeo de resolução de problemas de exemplo para guia de resolução.)
Se você executar esse comando sem shards não atribuídos, vai receber um erro 400 dizendo que não consegue encontrar shards não atribuídos para explicar porque não há nada errado pararelatório.Se tiver uma causa não lógica (por exemplo, um erro temporário de rede, como node saiu do cluster durante a alocação), você pode usar o _cluster/reroute da Elastic.
POST /_cluster/rerouteEsta solicitação sem personalizações inicia um processo assíncrono em segundo plano que tenta alocar todos os shards com estado: não atribuídos. (Não faça como eu e não espere a conclusão do processo antes de contatar a equipe de desenvolvimento, pois achei que seria instantâneo e, coincidentemente, o problema foi escalado justamente quando eles disseram que não havia nada de errado, porque, na verdade, não havia mais nada.) Para obter mais informações, consulte este vídeo de solução de problemas para monitorar a saúde da alocação.
Circuit breakers
Maximizar a sua alocação de heap pode fazer com que as solicitações para o seu cluster atinjam o tempo limite ou causem erros e, com frequência, fará com que o seu cluster apresente exceções de circuit breaker. Erros de circuit breaker causam eventos no elasticsearch.log como:
Caused by: org.elasticsearch.common.breaker.CircuitBreakingException: [parent] Data too large, data for [<transport_request>] would be [num/numGB], which is larger than the limit of [num/numGB], usages [request=0/0b, fielddata=num/numKB, in_flight_requests=num/numGB, accounting=num/numGB]Para investigar, dê uma olhada em seu heap.percent, seja examinando _cat/nodes:
GET /_cat/nodes?v=true&h=name,node*,heap*
# heap = JVM (logical memory reserved for heap)
# ram = physical memory
name node.role heap.current heap.percent heap.max
tiebreaker-0000000002 mv 119.8mb 23 508mb
instance-0000000001 himrst 1.8gb 48 3.9gb
instance-0000000000 himrst 2.8gb 73 3.9gbOu, se você já ativou antes, navegue até o Kibana > Stack Monitoring.

Se você confirmou que está atingindo seus circuit breakers de memória, considere aumentar a heap temporariamente para ter espaço para investigar. Ao investigar a causa raiz, procure em seu logging de auditoria, logging lento, clusterlogs ou elasticsearch.log pelos eventos consecutivos anteriores. Você vai procurar:
- Consultas caras, especialmente:
- Altas agregações de bucket
- Eu me senti muito bobo quando descobri que as buscas alocam temporariamente uma determinada parte da sua heap antes de executarem a consulta com base no tamanho da busca ou nas dimensões do bucket, então definir 10.000.000 estava realmente dando uma dor de cabeça na minha equipe de operações.
- mapeamentos não otimizados
- A segunda razão para me sentir boba foi quando pensei que fazer relatórios hierárquicos faria buscas melhores do que dados nivelados (não é o caso).
- Altas agregações de bucket
- Volume/ritmo de solicitação: geralmente consultas em lote ou assíncronas
É hora de redimensionar
Se esta não for a sua primeira vez atingindo circuit breakers ou se você suspeita que será um problema contínuo (por exemplo, atingindo 85% consistentemente, então é hora de analisar o redimensionamento de recursos), você vai querer examinar mais de perto a JVM Memory Pressure como seu indicador de heap de longo prazo. Você pode verificar isso em Elastic Cloud Hosted > Deployment.

Ou você pode calcular a partir de _nodes/stats:
GET /_nodes/stats?filter_path=nodes.*.jvm.mem.pools.old
{"nodes": { "node_id": { "jvm": { "mem": { "pools": { "old": {
"max_in_bytes": 532676608,
"peak_max_in_bytes": 532676608,
"peak_used_in_bytes": 104465408,
"used_in_bytes": 104465408
}}}}}}}Onde:
JVM Memory Pressure = used_in_bytes / max_in_bytesUm possível sintoma disso é a alta frequência e a longa duração dos eventos do coletor de lixo (gc) em seu elasticsearch.log:
[timestamp_short_interval_from_last][INFO ][o.e.m.j.JvmGcMonitorService] [node_id] [gc][number] overhead, spent [21s] collecting in the last [40s]Se você confirmar esse cenário, precisará pensar em redimensionar seu cluster ou reduzir as demandas que o atingem. Convém investigar/considerar:
- Aumento dos recursos de heap (heap/nó, número de nós)
- Redução dos shards (excluir dados desnecessários/antigos; use o ILM para colocar dados em armazenamento warm/cold para que você possa encolhê-los; desative réplicas para dados que você não se importa em perder)
Estamos aqui para ajudar
Uau! Pelo que vejo no Suporte da Elastic, esse é o resumo dos tíquetes mais comuns dos usuários: shards não atribuídos, relação shard-heap desbalanceada, circuit breakers, alta coleta de lixo e erros de alocação. Todos são sintomas da conversa básica sobre gerenciamento de alocação de recursos. Espero que agora você também conheça a teoria e as etapas de resolução.
Neste ponto, porém, se você não conseguir resolver um problema, fique à vontade para entrar em contato. Teremos o maior prazer em ajudar! Fale conosco:
- Elastic Discuss
- Comunidade Elastic no Slack
- Consultoria da Elastic
- Treinamento da Elastic
- Suporte da Elastic
Viva a nossa capacidade de autogerenciar a alocação de recursos do Elastic Stack sem depender do pessoal de operações (mas sem deixar de amá-los)!
Recursos adicionais:
Publicado originalmente em 27 de abril de 2021; atualizado em 5 de novembro de 2024.
O lançamento e o tempo de amadurecimento de todos os recursos ou funcionalidades descritos neste artigo permanecem a exclusivo critério da Elastic. Os recursos ou funcionalidades não disponíveis no momento poderão não ser entregues ou não chegarem no prazo previsto.