...

Compreender e configurar de forma ideal o parâmetro vm.max_map_count do Linux para servidores de bases de dados

Vou explicar-te como vm.max_map_count compreender, medir e ajustar sem riscos em servidores de bases de dados Linux. Este artigo apresenta passos concretos, valores típicos e controlos comprovados na prática, para que o PostgreSQL, o MySQL/MariaDB, o Elasticsearch ou o OpenSearch funcionem corretamente sob carga.

Pontos centrais

  • Função: Limite máximo para as áreas de memória virtual (VMAs) por processo
  • Relevância: Bases de dados, sistemas de pesquisa, pilhas Java com muitos mapeamentos
  • Sintomas: „Não é possível alocar memória“, erros de arranque, falhas
  • Valores práticos: 262 144 a 1 048 576 para cargas de trabalho de grande dimensão
  • Procedimento: Avaliar as necessidades, aumentar com uma margem de segurança, integrar o acompanhamento

O que significa vm.max_map_count?

O parâmetro do kernel define quantos Áreas de memória (VMAs) que um único processo pode criar, no máximo. Cada operação mmap, cada objeto partilhado carregado, muitas alocações e blocos de memória partilhada aumentam este número. Com isto, não estou a limitar a quantidade de RAM, mas sim a Quantidade das áreas separadas no espaço de endereços virtual. Os processos de grande dimensão podem utilizar muita memória com poucos mapeamentos de grande dimensão, enquanto as cargas de trabalho fragmentadas atingem rapidamente o limite devido a muitos mapeamentos pequenos. Quem utiliza software que consome muita memória tem de conhecer este limite máximo; caso contrário, só se aperceberá do erro quando o sistema estiver sob carga.

Por que razão os servidores de bases de dados são afetados

As bases de dados e os serviços de pesquisa funcionam em grande medida com mapa, memória partilhada, caches e inúmeras bibliotecas. As instâncias do PostgreSQL com muitas extensões e ligações, o MySQL/MariaDB com plug-ins ou o Elasticsearch/OpenSearch com muitos segmentos de índice geram muitos VMAs. Se o número se aproximar do limite, os mapeamentos adicionais falham e o processo reporta Erro de memória. É precisamente nessas situações que os serviços não arrancam, interrompem-se sob carga ou perdem nós nos clusters. Evito esse tipo de comportamento determinando antecipadamente o limite máximo necessário e definindo-o de forma correta.

Sintomas e riscos de um ajuste incorreto

Os sinais mais comuns de um limite demasiado baixo são Erro de arranque apesar de haver memória disponível. Serviços como o Elasticsearch apresentam a mensagem „Cannot allocate memory“, embora a máquina ainda tenha recursos disponíveis. Também ocorrem encerramentos esporádicos de processos, assim que, internamente, forem necessárias mais VMAs do que o permitido. Um valor demasiado elevado não causa, em regra, qualquer dano, porque o kernel apenas utiliza um pouco mais Administração necessário para as vm_area_structs. Isto só se torna relevante quando os processos criam efetivamente milhões de mapeamentos, o que as cargas de trabalho típicas de bases de dados geralmente não atingem.

Valores práticos e contextualização

Muitas distribuições definem valores predefinidos conservadores em torno de 65 536, o que é suficiente para serviços simples, mas fica insuficiente para cargas de pesquisa e análise. Em configurações típicas de alojamento, utilizo 262 144 como um valor inicial sólido para pilhas de maior dimensão. Para instâncias muito grandes do Elasticsearch/OpenSearch, prevejo 1 048 576, desde que os dados de medição apontem nessa direção. Um valor mais elevado não traz qualquer benefício direto Aumento de desempenho, evita erros quando são necessários muitos mapeamentos. A documentação do kernel do Linux e os relatórios práticos mais comuns confirmam esta classificação.

Tipo de aplicação Perfil VMA (típico) Valor inicial de vm.max_map_count Limite máximo (se necessário)
Pequenas bases de dados / Ferramentas baixo-médio 65.536 262.144
PostgreSQL/MySQL médio-alto 262.144 524.288
Elasticsearch/OpenSearch elevado-muito elevado 262.144 1.048.576
Grandes pilhas de Java médio-alto 262.144 524.288

Avaliar as necessidades atuais

Antes de cada alteração, verifico a versão atual Definição com sysctl vm.max_map_count ou por cat /proc/sys/vm/max_map_count. Em seguida, determino as necessidades reais de um processo com wc -l /proc//maps, idealmente sob carga. Este valor varia consoante os módulos, as caches e a carga de trabalho; por isso, faço um acompanhamento ao longo de vários períodos de carga. Assim que o pico atinge 50–70 % do limite, defino uma reserva adequada. Desta forma, tomo uma decisão fundamentada Decisão em vez de adivinhar.

Como posso ajustar o vm.max_map_count de forma segura?

Para os testes, defino o valor temporariamente com sysctl -w vm.max_map_count=262144, o que tem efeito imediato e desaparece quando se reinicia o sistema. Para um funcionamento contínuo, introduzo o valor em /etc/sysctl.conf e carrega-o com sysctl --system novo, para que a Configuração permanece. Os grandes clusters de pesquisa ou as pilhas de bases de dados altamente modulares beneficiam, dependendo da medição, de 524 288 a 1 048 576. Aumento gradualmente, verifico os registos e observo as métricas relativas à utilização da memória. É assim que mantenho o Risco é reduzido durante o funcionamento e permite acumular reservas de forma planeada.

Melhores práticas para ambientes produtivos

Faço medições repetidas sob carga normal e de pico, em vez de me basear em valores pontuais. Não defino o limite máximo exatamente no valor máximo observado, mas sim com um fator de dois a quatro acima desse pico. Nos clusters, escolho valores consistentes para que todos os nós reajam da mesma forma e nenhum Excedentes gerar. O monitorização verifica erros relacionados com mmap/malloc, bem como a evolução do número de VMAs por processo. Antes da entrada em produção, testo novas Valores no ambiente de teste, com uma carga comparável.

Interação com outros parâmetros do kernel: swappiness, rácios de arquivos sujos, limites de ficheiros

O vm.max_map_count nunca existe isoladamente, pois outros parâmetros de ajuste influenciam isso Conduta O mesmo se aplica. O parâmetro «swappiness» determina com que agressividade o sistema transfere páginas para a memória swap, o que pode aumentar as latências. Os Dirty Ratios controlam quando as páginas alteradas regressam ao disco, podendo assim suavizar ou agravar os picos de E/S. Os limites para ficheiros abertos determinam quantos ficheiros e sockets as bases de dados podem manter em paralelo. Verifico estes Parâmetros em conjunto, para que não surja um novo estrangulamento.

Verificar de forma seletiva as «Transparent Huge Pages»

O THP influencia a gestão da memória ao agrupar páginas grandes, alterando assim os padrões de acesso. As bases de dados reagem de forma sensível ao THP, dependendo da carga de trabalho, razão pela qual verifico o estado e o modo e os defino para „madvise“ ou „never“ quando as latências aumentam. Encontre detalhes sobre os efeitos e o ajuste na minha nota sobre Páginas enormes transparentes em resumo. O importante é comprovar a alteração com métricas e não proceder à mudança às cegas. Assim, o Comportamento de armazenamento compreensível e reproduzível.

Compreender o VFS Cache Print

A cache VFS armazena metadados e conteúdos de ficheiros na memória principal, competindo assim com as páginas da base de dados. Com o parâmetro para o Impressão da cache VFS Influo na rapidez com que o sistema liberta esta cache. Uma pressão demasiado elevada pode aumentar a carga de E/S; uma pressão demasiado baixa deslocará as caches da base de dados e prejudicará as latências. Faço ajustes em pequenos passos e avalio os efeitos na taxa de acertos da cache de páginas, no tempo de espera de E/S e no débito. Isto Afinação fina tem frequentemente um impacto maior do que o esperado, quando as bases de dados e os sistemas de ficheiros funcionam em estreita interligação.

Diretrizes NUMA e bases de dados

As arquiteturas NUMA distribuem a memória pelos nós, o que influencia os tempos de acesso. Sem diretrizes adequadas, as páginas acabam nos nós „errados“, o que aumenta as latências e as falhas de cache. Fornecerei informações sobre modos e políticas em Diretrizes NUMA, incluindo parâmetros iniciais orientados para a prática. Para processos de base de dados de grande dimensão, defino nós preferenciais e verifico o interleaving, para que os acessos à memória local permanecer. A interação com o vm.max_map_count tem um efeito positivo quando os processos recebem muitos mapeamentos através de estratégias NUMA consistentes.

Como surgem os VMAs – e por que razão podem explodir

Distingo três fontes principais de VMAs: (1) mapeamentos associados a ficheiros (por exemplo, segmentos de dados e de índice do Elasticsearch/OpenSearch), (2) mapeamentos anónimos através de alocadores (glibc, jemalloc, tcmalloc) e (3) pilhas para threads. Muitos pequenos objetos partilhados, código JIT (por exemplo, em JVMs) e padrões de alocação fragmentados geram áreas adicionais. Cada thread traz consigo, pelo menos, uma VMA de pilha; à medida que o número de threads de trabalho aumenta, também cresce o número de VMAs. Isso explica por que razão os sistemas atingem os seus limites mais cedo quando têm a mesma quantidade de dados, mas mais threads/plugins.

Importante: Faço uma distinção entre „muita memória“ e „muitos mapeamentos“. Áreas grandes e contínuas raramente constituem um problema. A situação torna-se crítica quando o software acede frequentemente a muitos objetos pequenos mapa utiliza (estratégias de alocação), carrega bibliotecas dinamicamente ou mapeia um grande número de ficheiros em paralelo.

A sobrecarga por VMA é moderada (algumas centenas de bytes de dados de gestão). Um limite mais elevado aumenta as estruturas teoricamente possíveis, sem ocupar memória RAM, desde que os processos não as utilizem. Só quando surgem realmente centenas de milhares a milhões de VMAs é que o trabalho de gestão do kernel se torna percetível de forma mensurável.

Aprofundar os métodos de medição: registar pontos de pico com precisão

  • Faço as medições em vários momentos do dia e durante picos de carga de trabalho (execuções em lote, reindexação, janelas de manutenção).
  • Não estou a monitorizar apenas um processo, mas sim todo o conjunto de serviços críticos (base de dados, sidecars, agentes de cópia de segurança e monitorização).
  • Para obter resultados repetíveis, faço uma distinção entre „a frio“ (cache de páginas vazio) e „a quente“ (cache cheio) e registo as diferenças.

Ferramentas úteis para localizar pontos de acesso VMA:

# Os 10 principais processos por número de VMA
for p in /proc/[0-9]*; do
 pid=${p##*/}; test -r "$p/maps" || continue
 c=$(wc -l /dev/null || echo 0)
 cmd=$(tr -d '\0' /dev/null)]}"
done | sort -k2,2nr | head -n 10

No caso dos clusters, analiso os resultados em vários nós e procuro valores atípicos sistemáticos (por exemplo, determinados shards, extensões específicas ou versões). Defino alertas quando um processo atinge um valor superior a 70 % do limite ou quando a carga máxima apresenta uma tendência de crescimento.

Resolução de problemas: mensagens típicas de registo e verificações

Quando se atinge o limite, vejo frequentemente mensagens como „Cannot allocate memory“, „mmap failed“, „failed to map segment from shared object“ ou falhas no arranque sem que haja uma escassez evidente de RAM. Nessa altura, verifico o seguinte:

  • grep -i mmap /var/log/* e registos específicos do serviço relativos a alertas do ENOMEM
  • Número atual de mapeamentos: wc -l /proc//maps
  • Limites de Ulimit/Nofile, porque muitos ficheiros segmentados não são mapeados de forma adequada sem um número suficiente de ficheiros abertos
  • Número de tópicos (ps -eLo pid,comm,nlwp | sort -k3 -nr | head), uma vez que muitos threads aumentam o valor do VMA

Estabeleço uma correlação entre estes resultados e os perfis de carga (criação de índices, Vacuum/Analyze, importações em grande escala). Se o valor do VMA apresentar picos bem definidos em relação a tarefas específicas, dimensiono a reserva em conformidade.

Contentores, nuvens e orquestração: particularidades

Em contentores está vm.max_map_count na prática, na maioria das vezes, uma Configuração do anfitrião. Defino o valor no nó (Bare Metal ou VM) através de sysctl e carregá-lo de forma permanente através de /etc/sysctl.conf ou ficheiros em /etc/sysctl.d/. Em ambientes Docker, embora eu possa --sysctl Embora o vm.max_map_count pareça ter efeito a nível do host, estou a planear esta alteração como uma medida a nível do nó. Nos orquestradores (por exemplo, o Kubernetes), prefiro definir o valor através do Node-Init/Cloud-Init ou da imagem da máquina, para que os pods sem privilégios sejam iniciados corretamente. Importante: documento a configuração escolhida Linha de conformidade (que tipo de nó contém que valor), para que a programação e o auto-scaling se mantenham consistentes.

Automatização e conformidade

Registo a configuração „como código“, por exemplo, na gestão de configurações. A título de exemplo, utilizo um ficheiro «drop-in» do sysctl:

# /etc/sysctl.d/90-db-mappings.conf
vm.max_map_count = 524288

A implementação é feita de forma controlada (Staging → Canary → Implementação em larga escala). Imediatamente após as implementações, verifico através de verificações de integridade e confirmo se os novos pods/serviços apresentam o mesmo limite. Para efeitos de auditoria, registo os dados de medição (VMA de pico, fator de reserva, data do último ajuste) na documentação operacional.

Ajuste com Overcommit e OOM-Killer

Um limite de VMA mais elevado não reduz a ocupação da RAM, mas permite mais mapeamentos. Em picos de trabalho, a interação com estratégias de overcommit e o OOM-Killer pode tornar-se relevante: se eu permitir mais mapeamentos, os processos podem reservar memória de forma mais agressiva. Por isso, considero que vm.overcommit_memory e vm.overcommit_ratio tenho isso em atenção e garanto reservas claras (swap/headroom) ou políticas de overcommit mais restritivas, quando as cargas de trabalho tendem a causar sobrecarga. O objetivo é criar uma janela de alerta prévio: em vez de um erro OOM repentino, recebo antecipadamente sinais de aumento das taxas de erro/latência na monitorização, que indicam a necessidade de tomar medidas corretivas.

Casos extremos: 32 bits, muitos threads, escolha do alocador

  • Processos de 32 bits: O espaço de endereços virtual é mais limitado, pelo que a fragmentação torna-se mais rapidamente um problema. Um valor mais elevado de vm.max_map_count não resolve a falta de espaço de endereços – neste caso, o que ajuda são as compilações de 64 bits ou a mudança de arquitetura.
  • Serviços com muitos threads: Cada thread ocupa, no mínimo, uma VMA de pilha própria. Se o número de workers aumentar significativamente, o número de VMAs cresce linearmente. Asseguro-me de que os conjuntos de threads sejam limitados e dimensionados de forma adequada.
  • Alocador: Alguns alocadores utilizam mapa excessivo para blocos grandes ou muitos blocos pequenos. Quando se verificam picos de VMA significativos, testo alocadores alternativos ou as suas opções de ajuste, a fim de reduzir o número de mapeamentos.
  • Bibliotecas partilhadas: Muitos módulos pequenos, carregados dinamicamente, fazem aumentar o número de mapeamentos. Vou verificar se é possível consolidar módulos ou remover plugins desnecessários.

Lista de verificação antes da alteração

  • Determinar e documentar os limites atuais
  • Medir picos de VMA específicos do processo em várias janelas de carga
  • Calcular a reserva (fator 2–4 acima do pico) e planear os testes de estadiuação
  • Verificar os limites associados (nofile), o número de threads, o THP, a swappiness e os rácios de páginas sujas
  • Ativar monitorização/alertas relativos à proximidade do VMA, erros de mmap e eventos OOM
  • Definir o percurso de implementação e de reversão (Canary, janela de manutenção, ficheiros sysctl.d)
  • Garantir e documentar a consistência do cluster/nó

Planeamento para clusters e crescimento

Não me limito a analisar a situação atual, mas também o crescimento previsto dos dados e dos índices. Novas funcionalidades, mais clientes ou extensões adicionais aumentam frequentemente o número de Mapeamentos. Por isso, prevejo uma margem de segurança acima do pico observado e documento a decisão de forma clara. Nos clusters, mantenho os valores sincronizados, para que os nós reajam de forma idêntica e o failover não falhe devido a limites. A verificação regular durante as janelas de manutenção garante a Continuidade das definições.

Em resumo: configuração segura para servidores de bases de dados

Verifico o limite atual, meço o número de VMA sob carga e defino o vm.max_map_count com uma margem de segurança. Para muitas cargas de trabalho de bases de dados e de pesquisa, o valor 262 144 funciona como valor inicial e 1 048 576 como nível superior, caso os valores medidos e o crescimento assim o exijam. Esta alteração não resulta num aumento imediato do desempenho, mas evita erros quando são necessários muitos mapeamentos. A estabilidade é alcançada quando analiso em conjunto os registos, as métricas e os parâmetros do kernel relacionados. Desta forma, o Operação de bases de dados resistente, previsível e preparado para cargas crescentes.

Artigos actuais