paint-brush
O design e a implementação do Presto Local Cache na Uberpor@bin-fan
686 leituras
686 leituras

O design e a implementação do Presto Local Cache na Uber

por Bin Fan2022/06/03
Read on Terminal Reader
Read this story w/o Javascript

Muito longo; Para ler

No blog anterior, apresentamos os casos de uso do Presto do Uber e como colaboramos para implementar o cache local Alluxio para superar diferentes desafios na aceleração de consultas Presto. A segunda parte discute as melhorias nos metadados do cache local.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - O design e a implementação do Presto Local Cache na Uber
Bin Fan HackerNoon profile picture


No blog anterior, apresentamos os casos de uso do Presto do Uber e como colaboramos para implementar o cache local do Alluxio para superar diferentes desafios na aceleração de consultas do Presto. A segunda parte discute as melhorias nos metadados do cache local.

Metadados em nível de arquivo para cache local

Motivação

Primeiro, queremos evitar o cache obsoleto. Os arquivos de dados subjacentes podem ser alterados pelas estruturas de terceiros. Observe que essa situação pode ser rara em tabelas Hive, mas muito comum em tabelas Hudi.


Em segundo lugar, as leituras diárias de dados não duplicados do HDFS podem ser grandes, mas não temos espaço em cache suficiente para armazenar todos os dados. Portanto, podemos introduzir o gerenciamento de cota com escopo definindo uma cota para cada tabela.


Em terceiro lugar, os metadados devem ser recuperáveis após a reinicialização do servidor. Armazenamos metadados no cache local na memória em vez de no disco, o que impossibilita a recuperação de metadados quando o servidor é desativado e reiniciado.

Abordagem de alto nível

Portanto, propomos o File Level Metadata, que contém e mantém o horário da última modificação e o escopo de cada arquivo de dados que armazenamos em cache. O armazenamento de metadados em nível de arquivo deve ser persistente no disco para que os dados não desapareçam após a reinicialização.


Com a introdução de metadados em nível de arquivo, haverá várias versões dos dados. Um novo timestamp é gerado quando os dados são atualizados, correspondendo a uma nova versão. Uma nova pasta armazenando a nova página é criada correspondente a esse novo carimbo de data/hora. Ao mesmo tempo, tentaremos remover o carimbo de data/hora antigo.

Dados de Cache e Estrutura de Metadados

Conforme mostrado acima, temos duas pastas correspondentes a dois timestamps: timestamp1 e timestamp2. Normalmente, quando o sistema está rodando, não haverá dois timestamps simultaneamente, pois vamos deletar o antigo timestamp1 e manter apenas o timestamp2. No entanto, no caso de um servidor ocupado ou de alta simultaneidade, podemos não conseguir remover o carimbo de data/hora na hora, caso em que podemos ter dois carimbos de data/hora ao mesmo tempo. Além disso, mantemos um arquivo de metadados que contém as informações do arquivo no formato protobuf e o registro de data e hora mais recente. Isso garante que o cache local do Alluxio leia apenas os dados do timestamp mais recente. Quando o servidor é reiniciado, as informações do carimbo de data/hora são lidas do arquivo de metadados para que a cota e o horário da última modificação possam ser gerenciados corretamente.


Reconhecimento de metadados

Contexto de Cache

Como o Alluxio é uma solução de cache genérica, ele ainda precisa do mecanismo de computação, como o Presto, para passar os metadados para o Alluxio. Portanto, no site do Presto, usamos o HiveFileContext. Para cada arquivo de dados da tabela Hive ou tabela Hudi, o Presto cria um HiveFileContext. O Alluxio faz uso dessas informações ao abrir um arquivo Presto.


Ao chamar o openFile, o Alluxio cria uma nova instância do PrestoCacheContext, que contém o HiveFileContext e tem o escopo (quatro níveis: banco de dados, esquema, tabela, partição), cota, identificador de cache (ou seja, o valor md5 do caminho do arquivo) e outra informação. Passaremos esse contexto de cache para o sistema de arquivos local. O Alluxio pode, assim, gerenciar metadados e coletar métricas.


Agregação de métricas por consulta no lado do Presto

Além de passar dados do Presto para o Alluxio, também podemos chamar de volta para o Presto. Ao realizar operações de consulta, saberemos algumas métricas internas, como quantos bytes de dados lidos atingiram o cache e quantos bytes de dados foram lidos do armazenamento HDFS externo.

Conforme mostrado abaixo, passamos o HiveFileContext contendo o PrestoCacheContext para o sistema de arquivos de cache local (LocalCacheFileSystem), após o qual o sistema de arquivos de cache local chama de volta (IncremetCounter) para o CacheContext. Em seguida, essa cadeia de retorno de chamada continuará no HiveFileContext e, em seguida, no RuntimeStats.


No Presto, RuntimeStats é usado para coletar informações de métricas ao executar consultas para que possamos realizar operações de agregação. Depois disso, podemos ver as informações sobre o sistema de arquivos de cache local na IU do Presto ou no arquivo JSON. Podemos fazer Alluxio e Presto trabalharem em conjunto com o processo acima. Do lado do Presto, temos melhores estatísticas; do lado do Alluxio, temos uma visão mais clara dos metadados.

Trabalho futuro

Ajuste de desempenho

Como o processo de retorno de chamada descrito acima faz o ciclo de vida do CacheContext crescer consideravelmente, encontramos alguns problemas com o aumento da latência do GC, que estamos trabalhando para solucionar.

Adote Cache Semântico (SC)

Implementaremos o Cache Semântico (SC) com base nos metadados em nível de arquivo que propomos. Por exemplo, podemos salvar as estruturas de dados em arquivos Parquet ou ORC, como rodapé, índice, etc.

Desserialização mais eficiente

Para obter uma desserialização mais eficiente, usaremos flatbuf em vez de protobuf. Embora o protobuf seja usado na fábrica do ORC para armazenar metadados, descobrimos que os metadados do ORC trazem mais de 20-30% do uso total da CPU na colaboração do Alluxio com o Facebook. Portanto, estamos planejando substituir o protobuf existente por um flatbuf para armazenar cache e metadados, o que deve melhorar significativamente o desempenho da desserialização.


Para resumir, junto com o blog anterior, esta série de blog em duas partes compartilha como criamos uma nova camada de cache dos dados quentes necessários para nossa frota Presto com base na recente colaboração de código aberto entre as comunidades Presto e Alluxio no Uber. Essa abordagem arquitetônica simples e limpa pode reduzir significativamente a latência do HDFS com SSD gerenciado e programação consistente de afinidade suave baseada em hash. Junte-se a mais de 9.000 membros em nosso canal Slack da comunidade para saber mais.

sobre os autores

Chen Liang é engenheiro de software sênior da equipe de análise interativa da Uber, com foco no Presto. Antes de ingressar na Uber, Chen foi engenheiro de software da equipe da plataforma Big Data do LinkedIn. Chen também é um committer e membro PMC do Apache Hadoop. Chen possui dois mestrados pela Duke University e Brown University


Dr. Beinan Wang é um engenheiro de software da Alluxio e é o committer do PrestoDB. Antes da Alluxio, ele era o líder técnico da equipe Presto no Twitter e construiu sistemas SQL distribuídos em grande escala para a plataforma de dados do Twitter. Ele tem doze anos de experiência trabalhando em otimização de desempenho, cache distribuído e processamento de dados de volume. Ele recebeu seu Ph.D. em engenharia da computação pela Syracuse University na verificação de modelo simbólico e verificação de tempo de execução de sistemas distribuídos.


Também publicado aqui.