A interpretação mais forte do design e arquitetura do Apache Hudi

Agradecimentos ao colaborador do Apache Hudi: Wang Xianghu pela tradução e contribuição.

Bem-vindo a prestar atenção à conta pública do WeChat: ApacheHudi

Este artigo apresentará os conceitos básicos, design e infraestrutura geral do Apache Hudi.

1. Introdução

O Apache Hudi (abreviação: Hudi) permite armazenar grandes quantidades de dados sobre o armazenamento compatível com o Hadoop e também fornece duas primitivas, que permitem o processamento de fluxo no data lake, além do processamento em lote clássico. As duas primitivas são:

  • Atualizar / excluir registros : O Hudi usa índices detalhados de nível de arquivo / registro para oferecer suporte a registros de atualização / exclusão, além de fornecer garantias de transação para operações de gravação. A consulta processa o último instantâneo enviado e com base nesta saída.

  • Fluxo de alterações : o Hudi fornece suporte de primeira classe para obter alterações de dados: você pode obter o fluxo incremental de todos os registros da tabela especificada que foram atualizados / inseridos / excluídos de um determinado momento e desbloquear novas poses de consulta (categorias).

Essas primitivas são estreitamente combinadas para desbloquear os recursos de streaming / processamento incremental com base na abstração do DFS. Se você estiver familiarizado com o processamento de fluxo, isso é semelhante a consumir eventos de tópicos kafka e usar o armazenamento de estado para acumular gradualmente resultados intermediários. Isso terá as seguintes vantagens na arquitetura: 1) Melhoria da eficiência: a ingestão de dados geralmente precisa lidar com atualizações, exclusões e impor restrições de chave exclusivas. No entanto, devido à falta de um sistema como o Hudi, que pode fornecer suporte padrão para essas funções, os engenheiros de dados costumam usar grandes lotes de tarefas para reprocessar um dia inteiro de eventos ou recarregar todo o banco de dados upstream toda vez que são executados, resultando em um grande número de tarefas. Os recursos de computação são desperdiçados. Como o Hudi suporta atualizações em nível de registro, ele fornece apenas uma melhoria de desempenho em ordem de magnitude para essas operações, processando apenas registros alterados e reescrevendo apenas as partes atualizadas / excluídas da tabela, em vez de reescrever a partição inteira da tabela ou mesmo a tabela inteira. 2) Pipelines ETL / derivados mais rápidos: após a ingestão de dados de sistemas externos, a próxima etapa é usar o Apache Spark / Apache Hive ou qualquer outra estrutura de processamento de dados para ETL esses dados para armazenamento de dados, aprendizado de máquina ou apenas análise de dados Aguarde alguns cenários de aplicativos. Normalmente, esses processos dependem novamente de tarefas em lote expressas em código ou SQL, que processarão em lote todos os dados de entrada e recalcularão todos os resultados de saída. Ao usar consultas incrementais em vez de consultas de captura instantânea para consultar uma ou mais tabelas de entrada, você pode acelerar bastante esses pipelines de dados, processando novamente apenas alterações incrementais das tabelas upstream, como acima, e depois upsert ou excluir a tabela derivada de destino. 3) Aquisição de dados atualizados: não é comum reduzir recursos e obter melhorias de desempenho. Afinal, geralmente usamos mais recursos (como memória) para melhorar o desempenho (como a latência da consulta). O Hudi removeu radicalmente o método tradicional de gerenciamento de conjuntos de dados e trouxe um benefício adicional ao processamento incremental de lotes: comparado com o data lake anterior, o pipeline executará tempos mais curtos e a entrega de dados será mais rápida. 4) Armazenamento unificado: com base nas três vantagens acima, o processamento mais rápido e leve no data lake existente significa que o armazenamento ou data marts especiais não são mais necessários com o objetivo de acessar dados quase em tempo real.

2. Princípios de design

Streaming de leitura / gravação : O Hudi baseia-se nos princípios do design e dos projetos de banco de dados a partir de zero para aplicar à entrada e saída de grandes conjuntos de dados para registrar fluxos. Para esse fim, o Hudi fornece uma implementação de índice que pode mapear rapidamente as chaves gravadas para o local do arquivo em que está localizado. Da mesma forma, para transmitir dados de saída, o Hudi adiciona e rastreia metadados em nível de registro por meio de suas colunas especiais, que podem fornecer um fluxo incremental preciso de todas as alterações. Autogerenciamento : Hudi percebeu que os usuários podem ter expectativas diferentes quanto à atualização dos dados (otimizada para gravação) e desempenho da consulta (otimizada para leitura / consulta) .Ele suporta três tipos de consulta, que fornecem instantâneos em tempo real, streaming incremental e versões anteriores Dados puros da coluna. A cada passo, o Hudi se esforça para se autogerenciar (como otimizar automaticamente o paralelismo dos programas de gravação e manter o tamanho do arquivo) e se auto-reparar (como reverter automaticamente os envios com falha), mesmo que isso aconteça um aumento nos custos de tempo de execução (como : Armazene em cache os dados de entrada na memória para analisar a carga de trabalho). Sem essas alavancas operacionais integradas / funções de autogerenciamento, os custos operacionais desses oleodutos em larga escala geralmente dobram. Tudo é um log : o Hudi também possui um design compatível com dados em nuvem, apenas anexável, que implementa o princípio de um sistema de armazenamento estruturado em log e pode gerenciar perfeitamente os dados de todos os provedores de nuvem.
Modelo de dados de valores-chave : em termos de gravação, a tabela Hudi é modelada como um conjunto de dados de pares de valores-chave, em que cada registro possui uma chave de registro exclusiva. Além disso, uma chave de registro também pode incluir um caminho de partição no qual os registros podem ser particionados e armazenados. Isso geralmente ajuda a reduzir o espaço de pesquisa para consultas de índice.

3. Desenho da mesa

Depois de entender a principal motivação técnica do projeto Hudi, vamos nos aprofundar no design do próprio sistema Hudi. Em um nível superior, o componente usado para gravar a tabela Hudi é incorporado em uma tarefa do Apache Spark de uma maneira suportada e gera um conjunto de arquivos representando a tabela Hudi no armazenamento habilitado para DFS. Em seguida, com certas garantias, mecanismos de consulta como Apache Spark, Presto e Apache Hive podem consultar a tabela. Os três principais componentes da tabela Hudi: 1) Metadados ordenados da linha do tempo. Semelhante ao log de transações do banco de dados. 2) Arquivo de dados com layout hierárquico: os dados realmente gravados na tabela. 3) Índice (várias implementações): mapeie o conjunto de dados que contém o registro especificado.

O Hudi fornece as seguintes funções para escrever e consultar dados básicos, o que o torna um módulo importante para grandes lagos de dados: 1) suporta upsert de índice rápido e conectável (); 2) eficiente, apenas verifica novos dados Consulta por volume; 3) liberação e reversão de dados atômicos, suporte ao Savepoint salvo; 4) leitura e gravação de isolamento de instantâneo projetado usando o estilo mvcc (controle de simultaneidade de várias versões); 5) usa estatísticas para gerenciar o tamanho do arquivo; 6) possui Compactação autogerenciada com atualização / delta de registro; 7) metadados da linha do tempo para modificação de dados; 8) atender ao GDPR (Regulamento Geral de Proteção de Dados) e funções de exclusão de dados.

3.1 Cronograma

Em sua essência, o Hudi mantém uma linha do tempo contendo todas as operações instantâneas executadas no conjunto de dados em diferentes momentos instantâneos para fornecer uma visualização instantânea da tabela, além de apoiar efetivamente a recuperação de dados em ordem de chegada. A linha do tempo é semelhante ao log de refazer / transação do banco de dados e consiste em um conjunto de instâncias da linha do tempo. O Hudi garante a atomicidade das operações realizadas na linha do tempo e a consistência da linha do tempo com base no tempo instantâneo. A linha do tempo é implementada como um conjunto de arquivos na pasta de metadados .hoodie, no caminho base da tabela. Especificamente, o instante mais recente é salvo como um único arquivo e o instante mais antigo é arquivado na pasta de arquivamento da linha do tempo para limitar o número de arquivos listados por gravadores e consultas. Um instante da linha do tempo do Hudi consiste nos seguintes componentes: 1) Tipo de operação: o tipo de operação executada no conjunto de dados; 2) Hora instantânea: a hora instantânea é geralmente um carimbo de data / hora (por exemplo: 20190117010349), que se baseia na hora de início da operação A ordem é monótona; 3) Status instantâneo: o status atual do instante; cada instante possui informações de metadados no formato avro ou json, que detalham o status da operação e o status do instante. Os principais tipos de operação instantânea são: 1) COMMIT: um commit significa gravar um conjunto de átomos de registro no conjunto de dados; 2) CLEAN: exclua a atividade em segundo plano da versão antiga do arquivo que não é mais necessária no conjunto de dados; 3) DELTA_COMMIT: processará em lote Grave gravações atômicas no conjunto de dados do tipo de armazenamento MergeOnRead, alguns dos quais só podem ser gravados no log incremental; 4) COMPACTION: Coordene as atividades em segundo plano da estrutura de dados diferencial no Hudi, por exemplo: atualização do log baseado em linha O arquivo se torna um formato de coluna. Internamente, a compactação aparece como uma confirmação especial na linha do tempo; 5) ROLLBACK: indica que a confirmação / confirmação incremental não teve êxito e foi revertida, excluindo todos os arquivos parciais gerados durante o processo de gravação; 6) SAVEPOINT: determinados arquivos O grupo está marcado como "salvo" para que o programa de limpeza não o exclua. Em caso de desastre / recuperação de dados, ajuda a restaurar o conjunto de dados para um determinado ponto na linha do tempo; 

3.2 Arquivos de dados

Hudi organiza a tabela em uma estrutura de pastas no caminho básico no DFS. Se a tabela estiver particionada, haverá outras partições no caminho básico.Estas partições são as pastas que contêm os dados da partição, muito semelhantes à tabela Hive. Cada partição é identificada exclusivamente pelo caminho da partição em relação ao caminho base. Dentro de cada partição, os arquivos são organizados em grupos de arquivos, identificados exclusivamente pelo ID do arquivo. Cada fatia contém o arquivo de coluna básico (* .parquet) e um conjunto de arquivos de log (* .log *) gerados em um determinado momento instantâneo confirmado / compactado, que contém a inserção / atualização do arquivo básico desde que o arquivo básico foi gerado . O Hudi usa o design do MVCC.A operação de compactação mescla os arquivos de log e os básicos para gerar novas partes de arquivo, enquanto a operação de limpeza exclui partes de arquivo não usadas / antigas para recuperar espaço no DFS.

 

3.3 Índice

O Hudi fornece operações eficientes de upsert através do mecanismo de indexação, que mapeará uma combinação de chave de registro + caminho de partição para um ID de arquivo.O mapeamento entre essa chave de registro e o grupo de arquivos / ID de arquivo é gravado no grupo de arquivos Não mudará mais desde o começo. Em resumo, esse grupo de arquivos de mapeamento contém todas as versões de um grupo de arquivos. Atualmente, o Hudi fornece três implementações de índice (HBaseIndex, HoodieBloomIndex (HoodieGlobalBloomIndex), InMemoryHashIndex) para mapear uma chave de registro para o ID do arquivo que contém o registro. Isso nos permitirá aumentar significativamente a velocidade de upsert sem precisar digitalizar todos os registros da tabela. O índice Hudi pode ser classificado de acordo com sua capacidade de consultar registros da partição: 1) Índice global: O ID do arquivo do mapa de chaves do registro pode ser consultado sem informações da partição. Por exemplo, o gravador pode passar nulo ou qualquer sequência como o caminho da partição, mas o índice ainda encontrará o local do registro. O índice global é muito útil quando é garantido que a chave de registro seja exclusiva em toda a tabela, mas o consumo da consulta aumenta funcionalmente com o tamanho da tabela. 2) Índice não global: Diferentemente do índice global, o índice não global depende do caminho da partição (partitionPath); para uma determinada chave de registro, ele encontrará apenas o registro no caminho da partição especificada. Isso é mais adequado para o cenário em que o caminho da partição e a chave de registro são sempre gerados ao mesmo tempo e, ao mesmo tempo, você pode aproveitar melhor escalabilidade, porque o consumo do índice de consulta está relacionado apenas ao tamanho do conjunto de dados gravado na partição.

4. Tipo de tabela

4.1 Cópia na gravação 表

Quando a tabela COW é gravada, os dados são gravados diretamente no arquivo de base (parquet) não gravam o arquivo de log. Portanto, a fatia de arquivo da tabela COW contém apenas o arquivo de base (um arquivo em parquet constitui uma fatia de arquivo). O Spark DAG com esse método de armazenamento é relativamente simples. O principal objetivo é usar o particionador para dividir o registro Hudi marcado RDD (o chamado marcado refere-se à consulta de índice, marcando a posição de cada registro de entrada na tabela) em uma série de atualizações e inserções. Para manter o tamanho do arquivo, primeiro inserimos Amostrando para obter um perfil de carga de trabalho, esse perfil registra a inserção e atualização do registro de entrada e a distribuição na partição e outras informações. Empacote os dados do novo, desta maneira: 1) Para atualizações, a versão mais recente do ID do arquivo será reescrita uma vez e use o novo valor para todos os registros alterados 2) Para inserções Os registros são compactados primeiro em cada caminho da partição No arquivo menor, até que o tamanho máximo configurado seja atingido. Todos os registros restantes depois disso serão empacotados em um novo grupo de arquivos novamente, e o novo grupo de arquivos também atenderá aos requisitos de tamanho máximo de arquivo. 

 

4.2 Mesclar na leitura 表

Ao gravar dados na tabela MOR, o registro será primeiro gravado rapidamente no arquivo de log e depois será mesclado com o arquivo base usando a operação de compactação na linha do tempo. Dependendo se a consulta lê o fluxo de captura instantânea mesclada ou o fluxo de alterações no log ou apenas o arquivo base não imerso, a tabela MOR suporta vários tipos de consulta. Em um nível alto, o gravador MOR passará pelos mesmos estágios que o gravador COW ao ler dados. Essas atualizações serão anexadas ao arquivo de log mais recente no arquivo mais recente e não serão mescladas. Para inserir, o Hudi suporta dois modos: 1) inserir no arquivo de log: tabela com arquivo de log indexável executará esta operação (índice HBase); 2) inserir arquivo em parquet: tabela sem arquivo de índice (como índice de Bloom) e Como a cópia na gravação (COW), os registros de entrada no local marcado são particionados para que todas as upserts enviadas para o mesmo ID de arquivo sejam agrupadas. Esse lote de upserts será gravado no arquivo de log como um ou mais blocos de log. O Hudi permite que o cliente controle o tamanho do arquivo de log. O WriteClient do Hudi é o mesmo para escritores de cópia na gravação (COW) e mesclagem na leitura (MOR). Várias rodadas de gravação de dados acumularão um ou mais arquivos de log. Esses arquivos de log, juntamente com os arquivos básicos de parquet (se houver), formam uma fatia de arquivo e essa fatia de arquivo representa uma versão completa do arquivo. Este tipo de mesa é a mais versátil e a mais avançada. Oferece grande flexibilidade para gravações (você pode especificar diferentes estratégias de compactação para absorver o tráfego de gravação intermitente) e consultas (como ponderar a atualização dos dados e o desempenho da consulta). Ao mesmo tempo, contém uma curva de aprendizado para controlá-lo em operação. 

 

5. Escreva design

5.1 Operação de gravação

Pode ser útil entender as três operações de gravação diferentes fornecidas pela fonte de dados Hudi ou pela ferramenta deltastreamer e como melhor usá-las. Essas operações podem ser selecionadas / alteradas em cada confirmação de commit / delta emitida para o conjunto de dados. 1) Operação de upsert: Esta é a operação padrão.Nesta operação, os registros de dados são marcados primeiro para inserção ou atualização consultando o índice e, em seguida, são executadas heurísticas para determinar a melhor forma de empacotá-las no armazenamento para otimizar o tamanho do arquivo E, finalmente, escreva o registro. Para casos de uso, como captura de alterações no banco de dados, é recomendável usar esta ação quando a entrada quase certamente contém atualizações. 2) Operação de inserção: Comparada com a upsert, a operação de inserção também executará heurísticas para determinar o método de empacotamento e otimizar o tamanho do arquivo, mas ignorará completamente a consulta de índice. Portanto, para casos de uso como desduplicação de log (combinada com a opção de duplicação de filtro mencionada abaixo), é muito mais rápido que o upsert. Isso também se aplica a casos de uso em que o conjunto de dados pode tolerar duplicatas, mas requer apenas que o Hudi tenha recursos de gerenciamento de gravação / recepção / transação incrementais. 3) operação de inserção em massa: as operações de upsert e de inserção manterão os registros de entrada na memória para acelerar a velocidade de cálculo da heurística de armazenamento; portanto, pode ser complicado para o caso de uso inicial de carregar / inicializar o conjunto de dados Hudi. A inserção em massa fornece a mesma semântica que a inserção e também implementa um algoritmo de gravação de dados com base na classificação, que pode expandir bem a carga inicial de centenas de terabytes. Mas este é apenas o melhor esforço para ajustar o tamanho do arquivo, não para garantir o tamanho do arquivo, como inserção / atualização.

5.2 Compressão

A compactação é uma operação instantânea, que usa um conjunto de fatias de arquivo como entrada, mescla todos os arquivos de log em cada fatia de arquivo com seu arquivo de arquivo base (arquivo em parquet) para gerar uma nova fatia de arquivo compactada e a grava como uma na linha do tempo confirmar. A compactação se aplica apenas ao tipo de tabela MOR durante a leitura e à estratégia de compactação (por padrão, selecione a fatia do arquivo com o maior log não compactado) para selecionar a fatia do arquivo a ser compactada. Essa estratégia de compactação será avaliada após cada operação de gravação. Em um nível alto, existem duas maneiras de compactação: 1) Compactação síncrona: A compactação aqui é executada de forma síncrona pelo próprio processo de gravação após cada gravação, ou seja, a próxima operação de gravação não pode ser iniciada até que a compactação seja concluída. Em termos de operação, isso é o mais simples, porque não há necessidade de organizar um processo de compactação separado, mas a atualização garantida dos dados é a mais baixa. No entanto, esse método ainda é muito útil se você puder compactar a partição de tabela mais recente em cada operação de gravação enquanto atrasa a compactação de partições antigas / atrasadas. 2) Compactação assíncrona: dessa maneira, o processo de compactação pode ser executado de forma assíncrona com a operação de gravação da tabela. Isso tem a vantagem óbvia de que a compactação não bloqueia o próximo lote de gravações de dados, resultando em atualização de dados quase em tempo real. Ferramentas como o Hudi DeltaStreamer suportam o modo contínuo de limites, onde as operações de compactação e gravação são executadas em um único cluster de tempo de execução do Spark dessa maneira.

5.3 Limpeza

A limpeza é uma operação instantânea básica, cujo objetivo é excluir arquivos antigos e limitar o espaço de armazenamento ocupado pela tabela. A limpeza será executada automaticamente após cada operação de gravação e use os metadados da linha do tempo em cache no servidor da linha do tempo para evitar a varredura de toda a tabela para avaliar a oportunidade de limpeza. O Hudi suporta dois métodos de limpeza: 1) limpeza por commit / deltacommits: este é o mais comum e deve ser usado em consultas incrementais. Dessa maneira, o Cleaner reterá todas as fatias de arquivo gravadas nos últimos N commit / delta, proporcionando efetivamente a capacidade de executar consultas incrementais em qualquer intervalo imediato. Embora isso seja muito útil para consultas incrementais, uma vez que todas as versões dos fragmentos de arquivo dentro do intervalo de configuração são mantidas, pode ser necessário mais espaço de armazenamento em determinados cenários de alto carregamento de gravação. 2) Limpeza por fatias de arquivo reservadas: Este é um método mais simples de limpeza. Aqui, salvamos apenas as últimas N fatias de arquivo em cada grupo de arquivos. Alguns mecanismos de consulta, como o Apache Hive, processam consultas muito grandes.Essas consultas podem levar várias horas para serem concluídas.Neste caso, defina N como grande o suficiente para não excluir arquivos que a consulta ainda pode acessar. O filme é muito útil. Além disso, a operação de limpeza garantirá que sempre haverá apenas uma fatia de arquivo (a mais recente) em cada grupo de arquivos.

5.4 Otimização de acesso ao DFS

O Hudi também executa várias funções principais de gerenciamento de armazenamento nos dados armazenados na tabela. A chave para armazenar dados no DFS é gerenciar o tamanho do arquivo, contar e recuperar o espaço de armazenamento. Por exemplo, o HDFS é notório por lidar com pequenas pressões de memória / colocação de arquivos / RPC no NameNode, que podem destruir a estabilidade de todo o cluster. Em geral, os mecanismos de consulta podem oferecer melhor desempenho em arquivos de colunas de tamanho adequado, pois podem amortizar efetivamente o custo da obtenção de estatísticas de colunas etc. Mesmo em alguns armazenamentos de dados na nuvem, a listagem de um diretório contendo um grande número de arquivos pequenos acarretará custos. Aqui estão alguns métodos eficientes de gravação, gerenciamento de armazenamento de dados do Hudi: 1) O recurso de processamento de arquivos pequenos analisará a carga de trabalho de entrada e distribuirá o conteúdo para o grupo de arquivos existente, em vez de criar um novo grupo de arquivos (isso resultará na geração de arquivos pequenos ) 2) Use um cache da linha do tempo no gravador, para que, desde que o cluster Spark não seja reiniciado toda vez, as operações de gravação subseqüentes não precisem listar o diretório DFS para obter a lista de fatias de arquivo no caminho da partição especificada. 3) O usuário também pode ajustar o coeficiente de proporção entre o tamanho do arquivo básico e o arquivo de log e a taxa de compactação desejada, de modo a dividir um número suficiente de inserções em um grupo de arquivos unificado, gerando, assim, um arquivo básico de tamanho adequado. 4) Ajuste de forma inteligente o grau paralelo da inserção em massa e você pode ajustar o grupo de arquivos inicial com o tamanho apropriado novamente. De fato, é essencial executar esta operação corretamente, porque o grupo de arquivos não pode ser excluído depois de criado e pode ser expandido apenas como descrito acima.

6. Inquérito

Em vista desse layout de dados flexível e abrangente e da rica linha do tempo, o Hudi pode suportar três maneiras diferentes de consultar tabelas, dependendo do tipo de tabela.

Tipo de consulta VACA MOR
Consulta de instantâneo A consulta é executada no arquivo básico mais recente em todas as fatias de arquivo em uma determinada tabela ou partição de tabela e o último registro enviado será exibido. Execute a consulta combinando os arquivos básicos mais recentes e os arquivos de log em todas as fatias de arquivo em uma determinada tabela ou partição de tabela, e você verá os registros gravados pela última operação delta-commit.
Consulta incremental Nos intervalos de tempo instantâneo inicial e final, a consulta é executada no arquivo básico mais recente (chamado janela de consulta incremental) e apenas as colunas especificadas pelo Hudi são usadas para extrair os registros gravados nessa janela. A consulta é realizada na última fatia do arquivo na janela de consulta incremental, dependendo da própria janela, a combinação de registros de leitura no bloco básico ou no bloco de log.
Ler consulta otimizada Igual à consulta de captura instantânea Acesse apenas arquivos básicos, fornecendo dados para uma determinada fatia de arquivo desde a última operação de compactação. Geralmente, a garantia do último grau de dados da consulta depende da estratégia de compactação

 

 

6.1 Consulta de instantâneo

Você pode visualizar a captura instantânea mais recente da tabela após um determinado delta de confirmação ou operação imediata. No caso de uma tabela MOR (mesclagem em tempo de leitura), ela fornece uma tabela quase em tempo real (alguns minutos) mesclando instantaneamente os arquivos básicos e os arquivos incrementais da fatia de arquivo mais recente. Para a cópia na gravação (COW), ele pode substituir as tabelas em parquet existentes (ou tabelas do mesmo tipo de arquivo básico), fornecendo upsert / delete e outras funções de gravação.

6.2 Consulta incremental

Você pode visualizar dados gravados recentemente, desde que uma determinada operação commit / delta commit imediata. Forneça efetivamente fluxos de alterações para permitir pipelines de dados incrementais.

6.3 Consulta otimizada para leitura

Você pode visualizar a captura instantânea mais recente da tabela para uma determinada operação imediata de consolidação / compactação. Somente os arquivos básicos / de coluna das últimas partes do documento são expostos à consulta, e o mesmo desempenho de consulta de coluna da tabela não Hudi é garantido.

Índice Ler consulta otimizada Consulta de instantâneo
Atraso nos dados Alta Baixo
Atraso na consulta Baixo Alta

  

Acho que você gosta

Origin www.cnblogs.com/leesf456/p/12710118.html
Recomendado
Clasificación