Pular para o conteúdo principal

Tipos de mensagem

Ao ingerir dados com os SDKs do Zerobus Ingest via gRPC, você escolhe como os registros são codificados em uma determinada transmissão. O Zerobus Ingest é compatível com quatro formatos de mensagem para que você possa equilibrar simplicidade, segurança de tipo e throughput para sua carga de trabalho: JSON, Protocol Buffers (protobuf), Apache Arrow e Avro (Beta). Cada formato é validado em relação ao esquema da sua tabela Delta antes que os dados sejam tornados duráveis. Consulte Gerenciamento de esquema.

Os mesmos 1.000 registros em três formatos de mensagem: protobuf como uma codificação de linha compacta e tipada, Apache Arrow como um lote colunar cujos metadados e buffers são amortizados em todo o lote, e JSON como texto legível com nomes de campo repetidos

O diagrama mostra JSON, protobuf e Apache Arrow. Isso não inclui Avro, que utiliza uma codificação compacta orientada a linhas semelhante ao protobuf.

Qual formato você deve usar?​

Formato

Melhor para

Notas

JSON

Introdução e produtores simples.

A opção mais simples, sem definição de esquema para compilar. Conveniente, mas mais lento do que os formatos binários para cargas de trabalho de alto volume.

Buffers de protocolo

Transmissões de produção, orientadas a linhas e de alto volume.

Codificação binária compacta e type-safe. Recomendado para a maioria das cargas de trabalho de produção. Requer um esquema compilado.

Apache Arrow

Cargas de trabalho colunares ou orientadas a lotes.

Envia lotes de registros do Apache Arrow diretamente, evitando a serialização linha a linha. Ideal quando seus dados já são colunares ou quando você realiza a ingestão em lotes. Consulte Usar o Arrow Flight com o Zerobus Ingest.

Avro (Beta)

Produtores orientados a linhas que já funcionam com Avro.

Codificação binária compacta orientada a linhas descrita por um esquema JSON, uma alternativa ao protobuf.

Formato

Melhor para

Notas

JSON

Introdução e produtores simples.

A opção mais simples, sem definição de esquema para compilar. Conveniente, mas mais lento do que os formatos binários para cargas de trabalho de alto volume.

Buffers de protocolo

Transmissões de produção, orientadas a linhas e de alto volume.

Codificação binária compacta e type-safe. Recomendado para a maioria das cargas de trabalho de produção. Requer um esquema compilado.

Apache Arrow

Cargas de trabalho colunares ou orientadas a lotes.

Envia lotes de registros do Apache Arrow diretamente, evitando a serialização linha a linha. Ideal quando seus dados já são colunares ou quando você realiza a ingestão em lotes. Consulte Usar o Arrow Flight com o Zerobus Ingest.

Avro (Beta)

Produtores orientados a linhas que já funcionam com Avro.

Codificação binária compacta orientada a linhas descrita por um esquema JSON, uma alternativa ao protobuf.

Os snippets abaixo mostram o formato de cada estrutura no SDK do Python. Eles pressupõem que você já tenha criado o cliente do SDK e conheça sua tabela de destino. Para a configuração completa (endpoint, tabela, service principal) e exemplos em todos os idiomas, consulte Use Zerobus Ingest.

JSON​

JSON é a maneira mais simples de começar: você envia registros como objetos JSON sem definição de esquema para compilar. É ideal para começar a operar, prototipar e para produtores onde a conveniência importa mais do que o throughput bruto. Para cargas de trabalho de produção de alto volume, um formato binário (protobuf ou Arrow) é mais eficiente.

Crie uma transmissão para registros JSON passando um nome de tabela para TableProperties sem descritor:

Python
table_properties = TableProperties(TABLE_NAME)
stream = sdk.create_stream(CLIENT_ID, CLIENT_SECRET, table_properties)

stream.ingest_record_offset({"device_name": "sensor-1", "temp": 22, "humidity": 55})

Para o passo a passo completo do JSON, consulte Escrever um cliente.

Buffers de protocolo​

O Protobuf fornece uma codificação binária compacta e segura quanto ao tipo, sendo o formato recomendado para a maioria das cargas de trabalho de produção orientadas a linhas. Você define um esquema Protobuf que se ajusta à sua tabela Delta de destino (consulte Esquema Protobuf), compila-o e o SDK ingere registros, um por um, via gRPC.

Usar protobuf requer três passos: gerar um esquema .proto que corresponda à sua tabela, compilá-lo para um módulo de linguagem e, em seguida, ingerir registros passando o descritor para TableProperties. O exemplo a seguir usa o SDK do Python.

1. Gere um esquema .proto a partir da sua tabela. O SDK Python inclui uma ferramenta generate_proto que lê sua tabela Delta e grava um esquema correspondente:

Bash
python -m zerobus.tools.generate_proto \
--uc-endpoint "https://<workspace-id>.cloud.databricks.com" \
--client-id "<client-id>" \
--client-secret "<client-secret>" \
--table "main.default.air_quality" \
--output "record.proto" \
--proto-msg "AirQuality"

O esquema gerado usa a sintaxe proto2, com um campo opcional para cada coluna Delta:

Protobuf
syntax = "proto2";
message AirQuality {
optional string device_name = 1;
optional int32 temp = 2;
optional int64 humidity = 3;
}

2. Compile o esquema para um módulo Python com o compilador protobuf:

Bash
pip install "grpcio-tools>=1.60.0,<2.0"
python -m grpc_tools.protoc --python_out=. --proto_path=. record.proto

Isso gera record_pb2.py.

3. Ingerir registros passando o descritor compilado para TableProperties (o default para protobuf). O SDK usa o descritor para serializar cada registro:

Python
import record_pb2

descriptor_bytes = record_pb2.AirQuality.DESCRIPTOR.file.serialized_pb
table_properties = TableProperties(TABLE_NAME, descriptor_bytes)
stream = sdk.create_stream(CLIENT_ID, CLIENT_SECRET, table_properties)

record = record_pb2.AirQuality(device_name="sensor-1", temp=22, humidity=55)
stream.ingest_record_offset(record)

O exemplo acima usa o SDK do Python. As ferramentas variam de acordo com a linguagem: alguns SDKs fornecem uma utilidade generate_proto que gera um .proto a partir da sua tabela, enquanto outros (como Go e TypeScript) compilam um .proto existente. Para os passos por linguagem, consulte as notas de protobuf em cada tab de SDK de Escrever um cliente. Para fontes de ferramentas e exemplos completos, consulte o repository do Zerobus SDK.

Apache Arrow​

A ingestão do Apache Arrow envia dados Arrow RecordBatch diretamente pela mesma conexão gRPC, em vez de converter cada linha para JSON ou protobuf primeiro. É a melhor escolha quando sua aplicação já produz dados Arrow ou quando você ingere linhas em lotes, especialmente para esquemas amplos, com muitos dados numéricos ou orientados a análises, onde a serialização linha a linha adiciona sobrecarga.

O Arrow também é uma boa opção para lotes muito grandes. Ao contrário dos métodos de lote JSON e protobuf, que são tudo ou nada e limitados pelo tamanho máximo por mensagem, o caminho do Arrow Flight divide um lote grande em mensagens de transporte menores que são enviadas e confirmadas individualmente. Consulte Os lotes do Arrow Flight são a exceção e Usar o Arrow Flight com o Zerobus Ingest.

Abra uma transmissão Arrow com um pyarrow.Schema e ingira dados RecordBatch:

Python
stream = sdk.create_arrow_stream(TABLE_NAME, schema, CLIENT_ID, CLIENT_SECRET)

stream.ingest_batch(batch)

Para o passo a passo completo do Arrow Flight, incluindo definição de esquema, processamento em lote e compressão, consulte Usar o Arrow Flight com o Zerobus Ingest.

Avro​

info

Beta

Esse recurso está em Beta. Para usá-lo, um administrador de workspace deve habilitar Suporte a Avro no Zerobus Ingest na página Pré-visualizações . Consulte Gerenciar prévias do Databricks.

O Apache Avro é um formato orientado a linhas, compacto, binário e baseado em esquema. Assim como o protobuf, cada registro é codificado em relação a um esquema em vez de carregar seus nomes de campo em linha, o que mantém os registros pequenos. A diferença é que o protobuf usa um descritor .proto compilado, enquanto o Avro descreve seus registros com um esquema escrito em JSON. A execução da ingestão de Avro ocorre via gRPC através dos SDKs Zerobus. Para saber quais SDKs suportam Avro, consulte o repository de SDKs Zerobus.

Avro é uma boa opção quando seu produtor já trabalha com Avro, por exemplo, quando lê dados de Avro de um sistema upstream ou já mantém um esquema de escritor de Avro.

Tratamento de esquema​

O Zerobus Ingest não usa um registro de esquema, e os registros na transmissão não carregam um ID de esquema ou impressão digital. Em vez disso, você fornece o esquema de gravação do Avro como JSON ao criar a transmissão, e cada registro nessa transmissão é decodificado em relação a esse esquema. O esquema é validado em relação à tabela Delta de destino com antecedência, de modo que um esquema incompatível é rejeitado antes que qualquer dado seja fluxo.

O esquema do gravador é fixo durante o ciclo de vida da transmissão. Para ingerir com um esquema diferente, crie uma nova transmissão.

Os campos Avro são emparelhados com as colunas Delta por nome em todos os níveis, portanto, a ordem dos campos no esquema de escrita não importa. Para saber como os tipos Avro são mapeados para colunas Delta e quais colunas não podem ser direcionadas, consulte Tipos Avro. Para saber como os registros são validados em relação à tabela, consulte Gerenciamento de esquema.

Um esquema de escritor Avro deve declarar cada tipo em linha. Não há suporte para referências de tipo nomeado, que reutilizam um tipo record, enum ou fixed nomeado em outro lugar no esquema referindo-se ao seu nome.

Como fornecer dados​

Esteja você usando um SDK ou não, você pode ingerir um valor de cada vez ou em lotes. O que difere é quem codifica os dados para Avro:

  • Com um SDK, você pode:

    • Permita que o SDK codifique seus dados : forneça ao SDK seus registros Avro e ele os codifica em relação ao esquema do gravador.
    • Enviar bytes Avro pré-codificados : se você já possui dados codificados em Avro, por exemplo, de um sistema upstream, o SDK os envia como estão.
  • Sem um SDK, ao chamar a API gRPC diretamente, você enviará apenas bytes Avro pré-codificados. Crie a transmissão com o esquema do gravador, em seguida, envie a codificação binária Avro bruta de seus dados, sem cabeçalho de arquivo de contêiner, prefixo de ID de registro de esquema ou impressão digital.

Escrever um cliente​

Os exemplos abaixo usam os SDKs de Python e Rust. Eles criam uma transmissão, enviam registros que o SDK codifica em relação ao esquema do gravador e liberam. Eles pressupõem que você já configurou o Zerobus Ingest (endpoint, tabela de destino e service principal). Consulte Usar o Zerobus Ingest. Para saber quais SDKs oferecem suporte ao Avro, consulte o repository Zerobus SDK.

Instale o SDK com o extra avro, que extrai o codificador fastavro:

Bash
pip install "databricks-zerobus-ingest-sdk[avro]"

Passe o esquema do gravador como uma strings JSON para TableProperties com a palavra-chave avro_schema, depois ingira os registros como dicionários:

Python
import json

from zerobus.sdk.sync import ZerobusSdk
from zerobus.sdk.shared import TableProperties

SERVER_ENDPOINT = "https://1234567890123456.zerobus.us-west-2.cloud.databricks.com"
DATABRICKS_WORKSPACE_URL = "https://dbc-a1b2c3d4-e5f6.cloud.databricks.com"
TABLE_NAME = "main.default.air_quality"
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"

SCHEMA = {
"type": "record",
"name": "AirQuality",
"fields": [
{"name": "device_name", "type": "string"},
{"name": "temp", "type": "int"},
{"name": "humidity", "type": "long"},
],
}

sdk = ZerobusSdk(SERVER_ENDPOINT, DATABRICKS_WORKSPACE_URL)
table_properties = TableProperties(TABLE_NAME, avro_schema=json.dumps(SCHEMA))
stream = sdk.create_stream(CLIENT_ID, CLIENT_SECRET, table_properties)

try:
for i in range(1000):
stream.ingest_record_offset(
{"device_name": f"sensor-{i}", "temp": 20 + (i % 5), "humidity": 55 + (i % 10)}
)
stream.flush()
finally:
stream.close()

Para enviar dados que você já codificou, passe o bytes bruto para ingest_record_offset diretamente, sem nenhum tipo de wrapper. O SDK os envia sem alterações. Os bytes devem ser um datum Avro sem esquema codificado em relação ao mesmo esquema de escrita. Eles são mostrados aqui como um literal, mas na prática eles vêm de um sistema upstream:

Python
# A schemaless Avro datum for {"device_name": "sensor-0", "temp": 21, "humidity": 55},
# encoded against the writer schema above: a length-prefixed "sensor-0", then temp
# and humidity as Avro varints.
payload = b"\x10sensor-0\x2a\x6e"
stream.ingest_record_offset(payload)

Relacionado​