ClickHouse + Graphite: como reduzir significativamente o consumo de espaço em disco

ClickHouse + Graphite: como reduzir significativamente o consumo de espaço em disco

Saudações, habr.

Se alguém explorar o sistema web de grafite e encontrei um problema de desempenho de armazenamento sussurro (IO, espaço em disco consumido), então a chance de ClickHouse ter sido lançado como um substituto deve tender a um. Esta declaração implica que uma implementação de terceiros já é usada como um daemon que recebe métricas, por exemplo escritor de carbono ou go-carbono.

ClickHouse resolve bem os problemas descritos. Por exemplo, depois de transferir 2TiB de dados do sussurro, eles cabem em 300GiB. Não vou me alongar na comparação em detalhes; há muitos artigos sobre esse assunto. Além disso, até recentemente, nem tudo era perfeito com nosso armazenamento ClickHouse.

Problemas com espaço consumido

À primeira vista, tudo deveria funcionar bem. Seguindo documentação, crie uma configuração para o esquema de armazenamento de métricas (mais retention), em seguida crie uma tabela de acordo com a recomendação do backend selecionado para graphite-web: carbono-clickhouse+grafite-clickhouse ou gráfico, dependendo de qual pilha é usada. E... a bomba-relógio explode.

Para entender qual deles, você precisa saber como funcionam as inserções e a trajetória de vida dos dados nas tabelas de motores da família *Mesclar Árvore ClickHouse (gráficos retirados de презентации Alexei Zatelepin):

  • inserido блок dados. No nosso caso, foram as métricas que chegaram.
    ClickHouse + Graphite: como reduzir significativamente o consumo de espaço em disco
  • Cada bloco é classificado de acordo com a chave antes de ser gravado no disco. ORDER BYespecificado ao criar a tabela.
  • Após a classificação, кусок (part) os dados são gravados no disco.
    ClickHouse + Graphite: como reduzir significativamente o consumo de espaço em disco
  • O servidor monitora em segundo plano para que não haja muitas dessas peças e lança em segundo plano слияния (merge, doravante mesclado).
    ClickHouse + Graphite: como reduzir significativamente o consumo de espaço em disco
    ClickHouse + Graphite: como reduzir significativamente o consumo de espaço em disco
  • O servidor para de executar mesclagens por conta própria assim que os dados param de fluir ativamente para o партицию (partition), mas você pode iniciar o processo manualmente com o comando OPTIMIZE.
  • Se houver apenas uma parte restante na partição, você não poderá executar a mesclagem usando o comando usual; você deve usar OPTIMIZE ... FINAL

Então, chegam as primeiras métricas. E eles ocupam algum espaço. Os eventos subsequentes podem variar um pouco dependendo de muitos fatores:

  • A chave de particionamento pode ser muito pequena (um dia) ou muito grande (vários meses).
  • A configuração de retenção pode caber em vários limites significativos de agregação de dados na partição ativa (onde as métricas são registradas), ou talvez não.
  • Se houver muitos dados, então os primeiros pedaços, que devido à fusão em segundo plano podem já ser enormes (se você escolher uma chave de particionamento não ideal), não se fundirão com pequenos pedaços novos.

E sempre termina do mesmo jeito. O espaço ocupado pelas métricas no ClickHouse só aumenta se:

  • não se aplica OPTIMIZE ... FINAL manualmente ou
  • não insira dados em todas as partições continuamente, para que mais cedo ou mais tarde uma mesclagem em segundo plano comece

O segundo método parece ser o mais fácil de implementar e, portanto, está incorreto e foi tentado primeiro.
Eu escrevi um script python bastante simples que enviou métricas fictícias para todos os dias nos últimos 4 anos e executei o cron a cada hora.
Como todo o funcionamento do ClickHouse DBMS se baseia no fato de que este sistema mais cedo ou mais tarde fará todo o trabalho em segundo plano, mas não se sabe quando, não pude esperar o momento em que as velhas peças enormes se dignassem a começar a se fundir com novos pequenos. Ficou claro que precisávamos procurar uma maneira de automatizar as otimizações forçadas.

ClickHouse + Graphite: como reduzir significativamente o consumo de espaço em disco

Informações nas tabelas do sistema ClickHouse

Vamos dar uma olhada na estrutura da tabela sistema.peças. Estas são informações abrangentes sobre cada parte de todas as tabelas no servidor ClickHouse. Contém, entre outras coisas, as seguintes colunas:

  • nome do banco de dados (database);
  • Nome da tabela (table);
  • nome e ID da partição (partition & partition_id);
  • quando a peça foi criada (modification_time);
  • data mínima e máxima em uma peça (o particionamento é feito por dia) (min_date & max_date);

Há também uma mesa sistema.graphite_retentions, com os seguintes campos interessantes:

  • nome do banco de dados (Tables.database);
  • Nome da tabela (Tables.table);
  • idade da métrica quando a próxima agregação deve ser aplicada (age);

Assim:

  1. Temos uma tabela de pedaços e uma tabela de regras de agregação.
  2. Combinamos sua interseção e obtemos todas as tabelas *GraphiteMergeTree.
  3. Estamos procurando todas as partições nas quais:
    • mais de uma peça
    • ou chegou a hora de aplicar a próxima regra de agregação, e modification_time mais antigo que este momento.

Implementação

Esse pedido

SELECT
    concat(p.database, '.', p.table) AS table,
    p.partition_id AS partition_id,
    p.partition AS partition,
    -- Самое "старое" правило, которое может быть применено для
    -- партиции, но не в будущем, см (*)
    max(g.age) AS age,
    -- Количество кусков в партиции
    countDistinct(p.name) AS parts,
    -- За самую старшую метрику в партиции принимается 00:00:00 следующего дня
    toDateTime(max(p.max_date + 1)) AS max_time,
    -- Когда партиция должна быть оптимизированна
    max_time + age AS rollup_time,
    -- Когда самый старый кусок в партиции был обновлён
    min(p.modification_time) AS modified_at
FROM system.parts AS p
INNER JOIN
(
    -- Все правила для всех таблиц *GraphiteMergeTree
    SELECT
        Tables.database AS database,
        Tables.table AS table,
        age
    FROM system.graphite_retentions
    ARRAY JOIN Tables
    GROUP BY
        database,
        table,
        age
) AS g ON
    (p.table = g.table)
    AND (p.database = g.database)
WHERE
    -- Только активные куски
    p.active
    -- (*) И только строки, где правила аггрегации уже должны быть применены
    AND ((toDateTime(p.max_date + 1) + g.age) < now())
GROUP BY
    table,
    partition
HAVING
    -- Только партиции, которые младше момента оптимизации
    (modified_at < rollup_time)
    -- Или с несколькими кусками
    OR (parts > 1)
ORDER BY
    table ASC,
    partition ASC,
    age ASC

retorna cada uma das partições da tabela *GraphiteMergeTree cuja fusão deve liberar espaço em disco. A única coisa que resta a fazer é passar por todos eles com um pedido OPTIMIZE ... FINAL. A implementação final também leva em consideração o fato de não haver necessidade de mexer em partições com gravação ativa.

Isso é exatamente o que o projeto faz otimizador de grafite-ch. Ex-colegas do Yandex.Market experimentaram em produção, o resultado do trabalho pode ser visto abaixo.

ClickHouse + Graphite: como reduzir significativamente o consumo de espaço em disco

Se você executar o programa em um servidor com ClickHouse, ele simplesmente começará a funcionar no modo daemon. A cada hora será executada uma solicitação, verificando se surgiram novas partições com mais de três dias que possam ser otimizadas.

Nossos planos imediatos são fornecer pelo menos pacotes deb e, se possível, também rpm.

Em vez de uma conclusão

Nos últimos mais de 9 meses estive dentro da minha empresa InnoGames passou muito tempo mexendo na interseção do ClickHouse com a web de grafite. Foi uma boa experiência, que resultou em uma rápida transição do Whisper para o ClickHouse como armazenamento de métricas. Espero que este artigo seja o início de uma série sobre as melhorias que fizemos em várias partes desta pilha e o que será feito no futuro.

Vários litros de cerveja e dias administrativos foram gastos no desenvolvimento do pedido, juntamente com v0devil, pelo qual quero expressar-lhe a minha gratidão. E também por revisar este artigo.

Página do projeto no github

Fonte: habr.com

Adicionar um comentário