Compactação de dados no Apache Ignite. Experiência Sberbank

Ao trabalhar com grandes volumes de dados, às vezes o problema de espaço insuficiente em disco pode se tornar agudo. Uma maneira de resolver esse problema é a compactação, pela qual, no mesmo equipamento, você pode aumentar o volume de armazenamento. Neste artigo, veremos como a compactação de dados funciona no Apache Ignite. Este artigo descreve apenas os métodos de compactação de disco implementados no produto. Outros métodos de compactação de dados (na rede, na memória), implementados e não, permanecerão fora do escopo.

Portanto, quando o modo de persistência está ativado, como resultado da alteração de dados nos caches, o Ignite começa a gravar no disco:

  1. Conteúdo do cache
  2. Write Ahead Log (doravante denominado WAL)

Um mecanismo chamado compactação WAL existe há muito tempo para compactar WALs. O Apache Ignite 2.8, lançado recentemente, introduziu mais dois mecanismos para compactar dados no disco: compactação de página em disco para compactar o conteúdo de caches e compactação de instantâneo de página WAL para compactar alguns registros WAL. Mais sobre todos esses três mecanismos abaixo.

Compactação de página em disco


Como funciona


Para começar, abordaremos brevemente como o Ignite armazena dados. Para armazenamento, a memória da página é usada. O tamanho da página é definido no início do nó e não pode ser alterado em estágios posteriores, também o tamanho da página deve ser uma potência de dois e um múltiplo do tamanho do bloco do sistema de arquivos. As páginas são carregadas na RAM do disco, conforme necessário; o tamanho dos dados no disco pode exceder a quantidade de RAM alocada. Se não houver espaço suficiente na RAM para carregar páginas do disco, páginas antigas e não utilizadas serão forçadas a sair da RAM.

Os dados são armazenados no disco da seguinte forma: um arquivo separado é criado para cada partição de cada grupo de cache; nesse arquivo, em ordem crescente de índice, as páginas vão uma após a outra. O identificador de página inteira contém o identificador do grupo de cache, o número da partição e o índice da página no arquivo. Assim, pelo identificador de página inteira, podemos identificar exclusivamente o arquivo e compensá-lo no arquivo para cada página. Você pode ler mais sobre a memória da página em um artigo no Apache Ignite Wiki: Ignite Persistent Store - sob o capô .

O mecanismo de compactação de página do disco, como o nome sugere, funciona no nível da página. Quando esse mecanismo é ativado, o trabalho com dados na RAM é executado como está, sem nenhuma compactação, mas no momento de salvar as páginas da RAM no disco, elas são compactadas.

Mas compactar cada página individualmente não é uma solução para o problema, você precisa reduzir o tamanho dos arquivos de dados resultantes. Se o tamanho da página deixar de ser corrigido, não será mais possível gravar as páginas em um arquivo, uma por uma, pois isso pode causar vários problemas:

  • Não podemos usar o índice da página para calcular o deslocamento em que está localizado no arquivo.
  • , , . , . , .
  • , , , .

Para não solucionar esses problemas em seu próprio nível, a compactação de páginas em disco no Apache Ignite usa um mecanismo do sistema de arquivos chamado arquivos esparsos. Um arquivo esparso é um arquivo no qual algumas regiões preenchidas com zeros podem ser marcadas como furos. Nesse caso, os blocos do sistema de arquivos para armazenar esses furos não serão alocados, como resultado do qual o espaço em disco é economizado.

É lógico que, para liberar o bloco do sistema de arquivos, o tamanho do furo seja maior ou igual ao bloco do sistema de arquivos, o que impõe uma restrição adicional ao tamanho da página do Apache Ignite: para que a compactação dê pelo menos algum efeito, o tamanho da página deve ser estritamente maior que o tamanho do bloco do sistema de arquivos . Se o tamanho da página for igual ao tamanho do bloco, nunca poderemos liberar um único bloco, pois para liberar um único bloco, precisamos de uma página compactada para ocupar 0 bytes. Se o tamanho da página for igual ao tamanho de 2 ou 4 blocos, já podemos liberar pelo menos um bloco se a página for compactada em pelo menos 50% ou 75%, respectivamente.

Assim, a descrição final do mecanismo: Ao gravar uma página no disco, é feita uma tentativa de compactar a página. Se o tamanho da página compactada permitir que um ou mais blocos do sistema de arquivos sejam liberados, a página será gravada em formato compactado, um "furo" será perfurado no lugar dos blocos liberados (é feita uma chamada do sistema fallocate()com o sinalizador "punch hole"). Se o tamanho da página compactada não permitir a liberação de blocos, a página será salva como está, na forma descompactada. Todas as compensações de página são consideradas e sem compactação, multiplicando o índice da página pelo tamanho da página. Não é necessária realocação automática de páginas. As compensações de página, bem como sem compactação, caem nos limites dos blocos do sistema de arquivos.



Na implementação atual, o Ignite só pode funcionar com arquivos esparsos no SO Linux, portanto, a compactação de página em disco só pode ser ativada quando o Ignite é usado neste sistema operacional.

Algoritmos de compactação que podem ser usados ​​para compactação de página em disco: ZSTD, LZ4, Snappy. Além disso, existe um modo operacional (SKIP_GARBAGE), no qual apenas um local não utilizado na página é descartado sem aplicar compressão aos dados restantes, o que permite reduzir a carga na CPU em comparação com os algoritmos listados acima.

Impacto no desempenho


Infelizmente, na verdade, não medi o desempenho em bases reais, pois não planejamos usar esse mecanismo na produção, mas teoricamente podemos especular onde vamos perder e onde vamos vencer.

Para fazer isso, precisamos lembrar como ler e escrever páginas ao acessá-las:

  • Quando uma operação de leitura é executada, ela é pesquisada primeiro na RAM; se a pesquisa falhar, a página é carregada na RAM do disco com o mesmo fluxo que lê.
  • Ao executar uma operação de gravação, a página na RAM é marcada como suja, enquanto o salvamento físico da página no disco imediatamente no fluxo que está executando a gravação não ocorre. Todas as páginas sujas são salvas no disco posteriormente no processo do ponto de verificação em fluxos separados.

Assim, o efeito nas operações de leitura:

  • (disk IO), .
  • (CPU), sparse . IO sparse ( sparse , , ).
  • (CPU), .
  • .
  • ( ):
  • (disk IO), .
  • (CPU, disk IO), sparse .
  • (CPU), .

Qual escala superará? Tudo depende muito do ambiente, mas estou inclinado a acreditar que a compactação de página em disco tem mais probabilidade de degradar o desempenho na maioria dos sistemas. Além disso, testes em outros DBMSs usando uma abordagem semelhante com arquivos esparsos mostram uma queda no desempenho quando a compactação está ativada.

Como habilitar e configurar


Como mencionado acima, a versão mínima do Apache Ignite que suporta compactação de página em disco: 2.8 e suporta apenas o sistema operacional Linux. A ativação e configuração são realizadas da seguinte maneira:

  • O caminho da classe deve ter um módulo de ignição-compressão. Por padrão, ele está localizado na distribuição Apache Ignite no diretório libs / opcional e não está incluído no caminho da classe. Você pode simplesmente mover o diretório um nível para libs e, em seguida, quando iniciado através do ignite.sh, ele será automaticamente ativado.
  • Persistence ( DataRegionConfiguration.setPersistenceEnabled(true)).
  • ( DataStorageConfiguration.setPageSize() ).
  • , () ( CacheConfiguration.setDiskPageCompression() , CacheConfiguration.setDiskPageCompressionLevel()).

WAL compaction



O que é o WAL e por que é necessário? Muito brevemente: este é um diário em que todos os eventos que mudam como resultado do repositório de páginas se enquadram. Ele é necessário principalmente para a possibilidade de recuperação em caso de queda. Antes de transferir o controle para um usuário, qualquer operação deve primeiro gravar o evento no WAL, para que, em caso de queda, seja possível executar o log e restaurar todas as operações pelas quais o usuário recebeu uma resposta bem-sucedida, mesmo que essas operações não tenham tempo para serem refletidas no armazenamento da página em disco (acima já foi descrito que a gravação real no armazenamento de páginas é realizada em um processo chamado de ponto de verificação com algum atraso em threads separados).

As entradas no WAL são divididas em lógica e física. Os lógicos são chaves e valores próprios. Físico - reflete as alterações da página no armazenamento de páginas. Se os registros lógicos puderem ser úteis para outros casos, os registros físicos serão necessários apenas para recuperação no caso de uma queda e os registros serão necessários apenas a partir do momento do último ponto de verificação bem-sucedido. Aqui, não entraremos em detalhes e explicaremos por que isso funciona dessa maneira, mas qualquer pessoa interessada pode consultar o artigo já mencionado no Apache Ignite Wiki: Ignite Persistent Store - sob o capô .

Um registro lógico geralmente responde por vários registros físicos. Ou seja, por exemplo, uma operação de colocação em cache afeta várias páginas na memória da página (uma página com os próprios dados, páginas com índices, páginas com listas gratuitas). Em alguns testes sintéticos, verificou-se que os registros físicos ocupavam até 90% do arquivo WAL. Além disso, eles precisam de um tempo muito curto (por padrão, o intervalo entre os pontos de verificação é de 3 minutos). Seria lógico se livrar desses dados depois de perder sua relevância. É exatamente isso que o mecanismo de compactação do WAL executa, livra-se dos registros físicos e compacta os demais registros lógicos com zip, enquanto o tamanho do arquivo diminui significativamente (às vezes dezenas de vezes).

Fisicamente, um WAL consiste em vários segmentos (padrão 10) de tamanho fixo (padrão de 64 MB), que são substituídos em um círculo. Assim que o segmento atual é preenchido, o próximo segmento é atribuído ao atual e o segmento preenchido é copiado para o arquivo morto em um fluxo separado. A compactação WAL já funciona com segmentos de arquivamento. Além disso, em um fluxo separado, ele monitora a execução do ponto de verificação e inicia a compactação por segmentos de archive, para os quais os registros físicos não são mais necessários.



Impacto no desempenho


Como a compactação WAL opera como um encadeamento separado, não deve haver uma influência direta nas operações executadas. Mas ainda fornece uma carga adicional em segundo plano na CPU (compactação) e no disco (lendo cada segmento WAL do arquivamento e gravando segmentos compactados); portanto, se o sistema for executado no limite, isso também levará à degradação do desempenho.

Como habilitar e configurar


Você pode ativar a compactação WAL usando a propriedade WalCompactionEnabledc DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). Além disso, usando o método DataStorageConfiguration.setWalCompactionLevel (), você pode definir a taxa de compactação se não estiver satisfeito com o valor padrão (BEST_SPEED).

Compactação de instantâneo da página WAL


Como funciona


Já descobrimos que no WAL, as entradas são divididas em lógicas e físicas. Para cada alteração de cada página na memória da página, é gerado um registro físico do WAL. Os registros físicos, por sua vez, também são divididos em duas subespécies: registro de instantâneo da página e registro delta. Sempre que alteramos algo em uma página e transferimos de um estado limpo para um sujo, uma cópia completa desta página é salva no WAL (registro de instantâneo da página). Mesmo que tenhamos alterado apenas um byte no WAL, um registro com um tamanho um pouco maior que o tamanho da página será salvo. Se alterarmos algo em uma página já suja, um registro delta é formado no WAL, que reflete apenas as alterações em comparação com o estado anterior da página, mas não a página inteira. Como a redefinição do status das páginas de sujo para limpo é realizada durante o processo do ponto de verificação,imediatamente após o início do ponto de verificação, quase todos os registros físicos consistirão apenas em instantâneos de páginas (como todas as páginas imediatamente após o início do ponto de verificação estão em branco); então, à medida que você se aproxima do próximo ponto de verificação, a proporção de registro delta começa a crescer e é redefinida novamente no início do próximo ponto de verificação. As medições em alguns testes sintéticos mostraram que o compartilhamento de instantâneos de página no volume total de registros físicos atinge 90%.

A idéia por trás da compactação de instantâneo de página do WAL é compactar instantâneos de página usando uma ferramenta de compactação de página pronta para uso (consulte compactação de página em disco). Ao mesmo tempo, no WAL, os registros são salvos sequencialmente no modo somente anexado e não há necessidade de vincular registros aos limites dos blocos do sistema de arquivos; portanto, aqui, diferentemente do mecanismo de compactação de página em disco, não precisamos absolutamente de arquivos esparsos, portanto esse mecanismo não funcionará apenas no SO Linux Além disso, não nos importamos mais com o quanto conseguimos compactar a página. Mesmo se liberamos 1 byte, esse já é um resultado positivo e podemos salvar dados compactados no WAL, ao contrário da compactação de página em disco, onde salvamos uma página compactada apenas se mais de 1 bloco do sistema de arquivos for liberado.

As páginas são dados bem compactáveis, sua participação no volume total do WAL é muito alta; portanto, sem alterar o formato do arquivo WAL, podemos obter uma redução significativa em seu tamanho. A compactação de registros lógicos, entre outras coisas, exigiria uma alteração no formato e perda de compatibilidade, por exemplo, para consumidores externos que possam estar interessados ​​em registros lógicos, sem reduzir significativamente o tamanho do arquivo.

Quanto à compactação de página em disco para compactação de instantâneo de página WAL, os algoritmos de compactação ZSTD, LZ4, Snappy e o modo SKIP_GARBAGE podem ser usados.

Impacto no desempenho


Não é difícil perceber que a inclusão direta da compactação de instantâneo da página WAL afeta apenas os fluxos que gravam dados na memória da página, ou seja, aqueles fluxos que alteram os dados nos caches. A leitura dos registros físicos do WAL ocorre apenas uma vez, no momento da elevação do nó após a queda (e apenas no caso de uma queda durante o ponto de verificação).

Isso afeta os fluxos de dados da seguinte maneira: obtemos um efeito negativo (CPU) devido à necessidade de compactar a página todas as vezes antes de gravar no disco e um efeito positivo (E / S de disco) reduzindo a quantidade de dados sendo gravados. Assim, tudo é simples aqui, se o desempenho do sistema estiver na CPU, obteremos um pouco de degradação, se na E / S do disco, obteremos um aumento.

Indiretamente, a redução do tamanho do WAL também afeta (positivamente) os fluxos que soltam segmentos WAL nos fluxos de arquivamento e compactação WAL.

Testes de desempenho real em nosso ambiente com dados sintéticos mostraram um pequeno aumento (taxa de transferência aumentada em 10% a 15%, latência diminuída em 10% a 15%).

Como habilitar e configurar


A versão mínima do Apache Ignite é 2.8. A ativação e configuração são realizadas da seguinte maneira:

  • O caminho da classe deve ter um módulo de ignição-compressão. Por padrão, ele está localizado na distribuição Apache Ignite no diretório libs / opcional e não está incluído no caminho da classe. Você pode simplesmente mover o diretório um nível para libs e, em seguida, quando iniciado através do ignite.sh, ele será automaticamente ativado.
  • A persistência deve estar ativada (ativada até DataRegionConfiguration.setPersistenceEnabled(true)).
  • DataStorageConfiguration.setWalPageCompression(), ( DISABLED).
  • DataStorageConfiguration.setWalPageCompression(), javadoc .


Os mecanismos de compactação de dados discutidos no Apache Ignite podem ser usados ​​independentemente um do outro, mas qualquer combinação deles também é válida. A compreensão dos princípios de seu trabalho determinará como eles se ajustam às suas tarefas no ambiente e o que você terá que sacrificar ao usá-las. A compactação de página em disco foi projetada para compactar o armazenamento principal e pode fornecer compactação média. A compactação de instantâneo da página WAL fornecerá um grau médio de compactação dos arquivos já WAL, enquanto é provável que melhore o desempenho. A compactação WAL não afetará positivamente o desempenho, mas minimizará o tamanho dos arquivos WAL, excluindo registros físicos.

All Articles