O canário de OOM é experimental e está desabilitado por padrão. Seu comportamento pode mudar
entre versões do ClickHouse até que a validação em produção seja concluída.
Visão geral
SIGKILL — geralmente o maior consumidor, que,
em um host dedicado, é o próprio clickhouse-server. Assim, o servidor inteiro é perdido
em vez de ter a chance de se recuperar.
O canário de OOM muda quem morre primeiro. Ele executa um pequeno processo filho
sacrificial que se torna o alvo de OOM mais atraente, para que o kernel o mate
em vez do servidor. O servidor então detecta a morte, confirma que foi um evento
de OOM e reduz a pressão de memória para conseguir sobreviver.
O canário não aumenta nenhum limite de memória e não substitui limites corretos
(veja Memory overcommit e
max_server_memory_usage). Ele é a última linha de defesa: troca uma pequena
quantidade fixa de memória por uma chance de sobreviver a um pico de uso de memória.
Como funciona
clickhouse oom-canary separado. Ele ajusta seu próprio
oom_score_adj para o valor máximo (1000) para que o kernel o escolha primeiro e, em seguida,
aloca, acessa e aplica mlock a oom_canary_size bytes (100 MB por padrão), para que
seu conjunto de memória residente seja real. Ele é encerrado automaticamente se o servidor for encerrado.
No servidor, uma thread de monitoramento observa o canário (via pidfd) e reage quando
ele morre:
- Encerrado por
SIGKILLcom evidência de OOM no cgroup → executa a resposta a OOM e, em seguida, relança um novo canário. - Encerrado sem evidência de OOM (por exemplo, um
kill -9manual), ou encerrado com uma falha transitória → apenas relança, sem resposta. - Falha permanente na inicialização, ou desligamento do servidor → o canário se desativa.
oom_kill de memory.events.local do cgroup v2.
Ela é deliberadamente local ao cgroup: contadores hierárquicos ou de todo o host podem
ser incrementados por processos não relacionados e acionariam respostas indevidas.
Em um OOM confirmado, a resposta executa estas etapas independentes: registrar uma mensagem FATAL,
limpar as arenas do alocador (jemalloc), tentar cancelar todas as
consultas em execução, cancelar todas as mesclagens e mutações e enfileirar um evento em
system.crash_log. Os logs do sistema não são
gravados de forma síncrona, porque forçar E/S sob pressão de memória pode piorar a situação.
Requisitos
- Linux ≥ 5.3. O monitor mantém controle do canário via
pidfd_open; em kernels mais antigos, o canário se desativa na inicialização. Isso é um no-op em plataformas que não sejam Linux. - cgroup v2 com
memory.events.localpara a resposta a OOM. Sem isso, o canário ainda é reiniciado após umSIGKILL, mas não consegue confirmar um OOM; portanto, a resposta nunca é executada (um aviso é registrado na inicialização). - capacidade de
mlock(opcional). Bloquear a memória do canário exigeCAP_IPC_LOCKou umRLIMIT_MEMLOCKsuficiente; se isso falhar, o canário registra um aviso, e sua memória pode ir para swap, enfraquecendo-o como alvo de OOM.
Configuração
Observabilidade
system.crash_log com signal = 9 e uma
signal_description mencionando OOM Canary: